1
|
|
|
<?php |
2
|
|
|
namespace Inji; |
3
|
|
|
/** |
4
|
|
|
* Tools object |
5
|
|
|
* |
6
|
|
|
* Toolkit with most needed functions |
7
|
|
|
* |
8
|
|
|
* @author Alexey Krupskiy <[email protected]> |
9
|
|
|
* @link http://inji.ru/ |
10
|
|
|
* @copyright 2015 Alexey Krupskiy |
11
|
|
|
* @license https://github.com/injitools/cms-Inji/blob/master/LICENSE |
12
|
|
|
*/ |
13
|
|
|
class Tools extends Model { |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Return random string |
17
|
|
|
* |
18
|
|
|
* @param int $length |
19
|
|
|
* @param string $characters |
20
|
|
|
* @return string |
21
|
|
|
*/ |
22
|
|
|
public static function randomString($length = 20, $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') { |
23
|
|
|
$charactersLength = strlen($characters); |
24
|
|
|
$randomString = ''; |
25
|
|
|
for ($i = 0; $i < $length; $i++) { |
26
|
|
|
$randomString .= $characters[rand(0, $charactersLength - 1)]; |
27
|
|
|
} |
28
|
|
|
return $randomString; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Clean and return user query params |
33
|
|
|
* |
34
|
|
|
* @param string $uri |
35
|
|
|
* @return array |
36
|
|
|
*/ |
37
|
|
|
public static function uriParse($uri) { |
38
|
|
|
$answerPos = strpos($uri, '?'); |
39
|
|
|
$params = array_slice(explode('/', substr($uri, 0, $answerPos ? $answerPos : strlen($uri))), 1); |
40
|
|
|
|
41
|
|
|
foreach ($params as $key => $param) { |
42
|
|
|
if ($param != '') { |
43
|
|
|
$params[$key] = urldecode($param); |
44
|
|
|
} else { |
45
|
|
|
unset($params[$key]); |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
return $params; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Recursive create dir |
53
|
|
|
* |
54
|
|
|
* @param string $path |
55
|
|
|
* @return boolean |
56
|
|
|
*/ |
57
|
|
|
public static function createDir($path) { |
58
|
|
|
if (file_exists($path)) { |
59
|
|
|
return true; |
60
|
|
|
} |
61
|
|
|
$root = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $_SERVER['DOCUMENT_ROOT']), '/') . '/'; |
62
|
|
|
if (strpos($path, $root) === 0) { |
63
|
|
|
$path = str_replace($root, '', $path); |
64
|
|
|
} |
65
|
|
|
$path = explode('/', $path); |
66
|
|
|
$cur = ''; |
67
|
|
|
foreach ($path as $item) { |
68
|
|
|
$cur .= $item . '/'; |
69
|
|
|
if (!file_exists($cur)) { |
70
|
|
|
mkdir($cur); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
return true; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
public static function delDir($dir) { |
77
|
|
|
if (!file_exists($dir)) { |
78
|
|
|
return true; |
79
|
|
|
} |
80
|
|
|
$files = array_diff(scandir($dir), array('.', '..')); |
81
|
|
|
foreach ($files as $file) { |
82
|
|
|
is_dir("$dir/$file") ? self::delDir("$dir/$file") : unlink("$dir/$file"); |
83
|
|
|
} |
84
|
|
|
return rmdir($dir); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Resize image in path |
89
|
|
|
* |
90
|
|
|
* @param string $img_path |
91
|
|
|
* @param int $max_width |
92
|
|
|
* @param int $max_height |
93
|
|
|
* @param string|false $crop |
94
|
|
|
* @param string $pos |
95
|
|
|
* @return string |
96
|
|
|
*/ |
97
|
|
|
public static function resizeImage($img_path, $max_width = 1000, $max_height = 1000, $crop = false, $pos = 'center') { |
98
|
|
|
ini_set("gd.jpeg_ignore_warning", 1); |
99
|
|
|
if (!getimagesize($img_path)) { |
100
|
|
|
return false; |
101
|
|
|
} |
102
|
|
|
list($img_width, $img_height, $img_type, $img_tag) = getimagesize($img_path); |
103
|
|
|
switch ($img_type) { |
104
|
|
|
case 1: |
105
|
|
|
$img_type = 'gif'; |
106
|
|
|
break; |
107
|
|
|
case 3: |
108
|
|
|
$img_type = 'png'; |
109
|
|
|
break; |
110
|
|
|
case 2: |
111
|
|
|
default: |
112
|
|
|
$img_type = 'jpeg'; |
113
|
|
|
break; |
114
|
|
|
} |
115
|
|
|
$imagecreatefromX = "imagecreatefrom{$img_type}"; |
116
|
|
|
$src_res = @$imagecreatefromX($img_path); |
117
|
|
|
if (!$src_res) { |
118
|
|
|
return false; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
if ($img_width / $max_width > $img_height / $max_height) { |
122
|
|
|
$separator = $img_width / $max_width; |
123
|
|
|
} else { |
124
|
|
|
$separator = $img_height / $max_height; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
if ($crop === true || $crop == 'q') { |
128
|
|
|
if ($img_width > $img_height) { |
129
|
|
|
$imgX = floor(($img_width - $img_height) / 2); |
130
|
|
|
$imgY = 0; |
131
|
|
|
$img_width = $img_height; |
132
|
|
|
$new_width = $max_width; |
133
|
|
|
$new_height = $max_height; |
134
|
|
View Code Duplication |
} else { |
|
|
|
|
135
|
|
|
$imgX = 0; |
136
|
|
|
$imgY = floor(($img_height - $img_width) / 2); |
137
|
|
|
$img_height = $img_width; |
138
|
|
|
$new_width = $max_width; |
139
|
|
|
$new_height = $max_height; |
140
|
|
|
} |
141
|
|
|
if ($pos == 'top') { |
142
|
|
|
$imgY = 0; |
143
|
|
|
} |
144
|
|
|
} elseif ($crop == 'c') { |
145
|
|
|
//Вычисляем некий коэффициент масштабирования |
146
|
|
|
$k1 = $img_width / $max_width; |
147
|
|
|
$k2 = $img_height / $max_height; |
148
|
|
|
$k = $k1 > $k2 ? $k2 : $k1; |
149
|
|
|
$ow = $img_width; |
150
|
|
|
$oh = $img_height; |
151
|
|
|
//Вычисляем размеры области для нового изображения |
152
|
|
|
$img_width = intval($max_width * $k); |
153
|
|
|
$img_height = intval($max_height * $k); |
154
|
|
|
$new_width = $max_width; |
155
|
|
|
$new_height = $max_height; |
156
|
|
|
//Находим начальные координаты (центрируем новое изображение) |
157
|
|
|
$imgX = (int) (($ow / 2) - ($img_width / 2)); |
158
|
|
|
if ($pos == 'center') { |
159
|
|
|
$imgY = (int) (($oh / 2) - ($img_height / 2)); |
160
|
|
|
} else { |
161
|
|
|
$imgY = 0; |
162
|
|
|
} |
163
|
|
View Code Duplication |
} else { |
|
|
|
|
164
|
|
|
$imgX = 0; |
165
|
|
|
$imgY = 0; |
166
|
|
|
$new_width = floor($img_width / $separator); |
167
|
|
|
$new_height = floor($img_height / $separator); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$new_res = imagecreatetruecolor($new_width, $new_height); |
171
|
|
|
imageAlphaBlending($new_res, false); |
172
|
|
|
imagesavealpha($new_res, true); |
173
|
|
|
imagecopyresampled($new_res, $src_res, 0, 0, $imgX, $imgY, $new_width, $new_height, $img_width, $img_height); |
174
|
|
|
|
175
|
|
|
if ($img_type == 'jpeg') { |
176
|
|
|
imageinterlace($new_res, 1); // чересстрочное формирование изображение |
177
|
|
|
imagejpeg($new_res, $img_path, 85); |
178
|
|
|
} else { |
179
|
|
|
$imageX = "image{$img_type}"; |
180
|
|
|
$imageX($new_res, $img_path); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
imagedestroy($new_res); |
184
|
|
|
imagedestroy($src_res); |
185
|
|
|
return $img_type; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
public static function imgToResource($path) { |
189
|
|
|
ini_set("gd.jpeg_ignore_warning", 1); |
190
|
|
|
if (!getimagesize($path)) { |
191
|
|
|
return false; |
192
|
|
|
} |
193
|
|
|
list($img_width, $img_height, $imgType, $img_tag) = getimagesize($path); |
|
|
|
|
194
|
|
|
switch ($imgType) { |
195
|
|
|
case 1: |
196
|
|
|
$imgType = 'gif'; |
197
|
|
|
break; |
198
|
|
|
case 3: |
199
|
|
|
$imgType = 'png'; |
200
|
|
|
break; |
201
|
|
|
case 2: |
202
|
|
|
default: |
203
|
|
|
$imgType = 'jpeg'; |
204
|
|
|
break; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
$imagecreatefromX = "imagecreatefrom{$imgType}"; |
208
|
|
|
$src_res = @$imagecreatefromX($path); |
209
|
|
|
return [ |
210
|
|
|
'res' => $src_res, |
211
|
|
|
'type' => $imgType |
212
|
|
|
]; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
public static function addWatermark($imagePath, $watermarkPath) { |
216
|
|
|
|
217
|
|
|
$image = self::imgToResource($imagePath); |
218
|
|
|
$watermark = self::imgToResource($watermarkPath); |
219
|
|
|
if (!$image || !$watermark || !$image['res'] || !$watermark['res']) { |
220
|
|
|
return false; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
$marge_right = 10; |
224
|
|
|
$marge_bottom = 10; |
225
|
|
|
$sx = imagesx($watermark['res']); |
226
|
|
|
$sy = imagesy($watermark['res']); |
227
|
|
|
|
228
|
|
|
imagecopy($image['res'], $watermark['res'], imagesx($image['res']) - $sx - $marge_right, imagesy($image['res']) - $sy - $marge_bottom, 0, 0, imagesx($watermark['res']), imagesy($watermark['res'])); |
229
|
|
|
|
230
|
|
|
if ($image['type'] == 'jpeg') { |
231
|
|
|
imageinterlace($image['res'], 1); // чересстрочное формирование изображение |
232
|
|
|
imagejpeg($image['res'], $imagePath, 85); |
233
|
|
|
} else { |
234
|
|
|
$imageX = "image{$image['type']}"; |
235
|
|
|
$imageX($image['res'], $imagePath); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
imagedestroy($watermark['res']); |
239
|
|
|
imagedestroy($image['res']); |
240
|
|
|
|
241
|
|
|
return true; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Send mail |
246
|
|
|
* |
247
|
|
|
* @param string $from |
248
|
|
|
* @param string $to |
249
|
|
|
* @param string $subject |
250
|
|
|
* @param string $text |
251
|
|
|
* @param string $charset |
252
|
|
|
* @param string $ctype |
253
|
|
|
* @return boolean |
254
|
|
|
*/ |
255
|
|
|
public static function sendMail($from, $to, $subject, $text, $charset = 'utf-8', $ctype = 'text/html') { |
256
|
|
|
$msg = compact('from', 'to', 'subject', 'text', 'charset', 'ctype'); |
257
|
|
|
$msg = Inji::$inst->event('sendMail', $msg); |
258
|
|
|
if (is_array($msg)) { |
259
|
|
|
$headers = "From: {$msg['from']}\r\n"; |
260
|
|
|
$headers .= "Content-type: {$msg['ctype']}; charset={$msg['charset']}\r\n"; |
261
|
|
|
$headers .= "Mime-Version: 1.0\r\n"; |
262
|
|
|
return mail($msg['to'], $msg['subject'], $msg['text'], $headers); |
263
|
|
|
} |
264
|
|
|
return $msg; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Redirect user from any place of code |
269
|
|
|
* |
270
|
|
|
* Also add message to message query for view |
271
|
|
|
* |
272
|
|
|
* @param string $href |
273
|
|
|
* @param string $text |
274
|
|
|
* @param string $status |
275
|
|
|
*/ |
276
|
|
|
public static function redirect($href = null, $text = false, $status = 'info') { |
277
|
|
|
if ($href === null) { |
278
|
|
|
$href = $_SERVER['REQUEST_URI']; |
279
|
|
|
} |
280
|
|
|
if ($text !== false) { |
281
|
|
|
\Inji\Msg::add($text, $status); |
282
|
|
|
} |
283
|
|
|
if (!headers_sent()) { |
284
|
|
|
header("Location: {$href}"); |
285
|
|
|
} else { |
286
|
|
|
echo '\'"><script>window.location="' . $href . '";</script>'; |
287
|
|
|
} |
288
|
|
|
exit("Перенаправление на: <a href = '{$href}'>{$href}</a>"); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Функция возвращает окончание для множественного числа слова на основании числа и массива окончаний |
293
|
|
|
* @param Integer $number Число на основе которого нужно сформировать окончание |
294
|
|
|
* @param String[] $endingArray Массив слов или окончаний для чисел (1, 4, 5), |
295
|
|
|
* например ['яблоко', 'яблока', 'яблок'] |
296
|
|
|
* @return String |
297
|
|
|
*/ |
298
|
|
|
public static function getNumEnding($number, $endingArray) { |
299
|
|
|
$number = $number % 100; |
300
|
|
|
if ($number >= 11 && $number <= 19) { |
301
|
|
|
$ending = $endingArray[2]; |
302
|
|
|
} else { |
303
|
|
|
$i = $number % 10; |
304
|
|
|
switch ($i) { |
305
|
|
|
case (1): |
306
|
|
|
$ending = $endingArray[0]; |
307
|
|
|
break; |
308
|
|
|
case (2): |
309
|
|
|
case (3): |
310
|
|
|
case (4): |
311
|
|
|
$ending = $endingArray[1]; |
312
|
|
|
break; |
313
|
|
|
default: |
314
|
|
|
$ending = $endingArray[2]; |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
return $ending; |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
/** |
321
|
|
|
* Clean request path |
322
|
|
|
* |
323
|
|
|
* @param string $path |
324
|
|
|
* @return string |
325
|
|
|
*/ |
326
|
|
|
public static function parsePath($path) { |
327
|
|
|
$path = str_replace('\\', '/', $path); |
328
|
|
|
$pathArray = explode('/', $path); |
329
|
|
|
$cleanPathArray = []; |
330
|
|
|
do { |
331
|
|
|
$changes = 0; |
332
|
|
|
foreach ($pathArray as $pathItem) { |
333
|
|
|
if (trim($pathItem) === '' || $pathItem == '.') { |
334
|
|
|
$changes++; |
335
|
|
|
continue; |
336
|
|
|
} |
337
|
|
|
if ($pathItem == '..') { |
338
|
|
|
array_pop($cleanPathArray); |
339
|
|
|
$changes++; |
340
|
|
|
continue; |
341
|
|
|
} |
342
|
|
|
$cleanPathArray[] = $pathItem; |
343
|
|
|
} |
344
|
|
|
$pathArray = $cleanPathArray; |
345
|
|
|
$cleanPathArray = []; |
346
|
|
|
} while ($changes); |
347
|
|
|
return (strpos($path, '/') === 0 ? '/' : '') . implode('/', $pathArray); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Show date in rus |
352
|
|
|
* |
353
|
|
|
* @param string $date |
354
|
|
|
* @return string |
355
|
|
|
*/ |
356
|
|
|
public static function toRusDate($date) { |
357
|
|
|
$yy = (int) substr($date, 0, 4); |
358
|
|
|
$mm = (int) substr($date, 5, 2); |
359
|
|
|
$dd = (int) substr($date, 8, 2); |
360
|
|
|
|
361
|
|
|
$hours = substr($date, 11, 5); |
362
|
|
|
|
363
|
|
|
$month = array('января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'); |
364
|
|
|
if (empty($month[$mm - 1])) { |
365
|
|
|
return 'Не указано'; |
366
|
|
|
} |
367
|
|
|
return ($dd > 0 ? $dd . " " : '') . $month[$mm - 1] . " " . $yy . " " . $hours; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Set header |
372
|
|
|
* |
373
|
|
|
* @param string $code |
374
|
|
|
* @param boolean $exit |
375
|
|
|
*/ |
376
|
|
|
public static function header($code, $exit = false) { |
377
|
|
|
if (!headers_sent()) { |
378
|
|
|
switch ($code) { |
379
|
|
|
case '404': |
380
|
|
|
header('HTTP/1.1 404 Not Found'); |
381
|
|
|
break; |
382
|
|
|
default: |
383
|
|
|
header($code); |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
if ($exit) { |
387
|
|
|
exit; |
388
|
|
|
} |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Return exist path from array |
393
|
|
|
* |
394
|
|
|
* If no exist path in array - return default |
395
|
|
|
* |
396
|
|
|
* @param array $paths |
397
|
|
|
* @param string|boolean $default |
398
|
|
|
* @return string|boolean |
399
|
|
|
*/ |
400
|
|
|
public static function pathsResolve($paths = [], $default = false) { |
401
|
|
|
foreach ($paths as $path) { |
402
|
|
|
if (file_exists($path)) { |
403
|
|
|
return $path; |
404
|
|
|
} |
405
|
|
|
} |
406
|
|
|
return $default; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* Convert acronyms to bites |
411
|
|
|
* |
412
|
|
|
* @param string $val |
413
|
|
|
* @return int |
414
|
|
|
*/ |
415
|
|
|
public static function toBytes($val) { |
416
|
|
|
$val = trim($val); |
417
|
|
|
$last = strtolower($val[strlen($val) - 1]); |
418
|
|
|
switch ($last) { |
419
|
|
|
case 'g': |
420
|
|
|
$val *= 1024; |
421
|
|
|
// no break |
422
|
|
|
case 'm': |
423
|
|
|
$val *= 1024; |
424
|
|
|
// no break |
425
|
|
|
case 'k': |
426
|
|
|
$val *= 1024; |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return $val; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Recursive copy directories and files |
434
|
|
|
* |
435
|
|
|
* @param string $from |
436
|
|
|
* @param string $to |
437
|
|
|
*/ |
438
|
|
|
public static function copyFiles($from, $to) { |
439
|
|
|
$from = rtrim($from, '/'); |
440
|
|
|
$to = rtrim($to, '/'); |
441
|
|
|
self::createDir($to); |
442
|
|
|
$files = scandir($from); |
443
|
|
|
foreach ($files as $file) { |
444
|
|
|
if (in_array($file, ['.', '..'])) { |
445
|
|
|
continue; |
446
|
|
|
} |
447
|
|
|
if (is_dir($from . '/' . $file)) { |
448
|
|
|
self::copyFiles($from . '/' . $file, $to . '/' . $file); |
449
|
|
|
} else { |
450
|
|
|
copy($from . '/' . $file, $to . '/' . $file); |
451
|
|
|
} |
452
|
|
|
} |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
public static function getDirContents($dir, &$results = array(), $curPath = '') { |
456
|
|
|
$files = scandir($dir); |
457
|
|
|
foreach ($files as $key => $value) { |
458
|
|
|
$path = realpath($dir . '/' . $value); |
459
|
|
|
if (!is_dir($path)) { |
460
|
|
|
$results[$path] = $curPath . '/' . $value; |
461
|
|
|
} else if ($value != "." && $value != "..") { |
462
|
|
|
self::getDirContents($path, $results, $curPath . '/' . $value); |
463
|
|
|
} |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
return $results; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
/** |
470
|
|
|
* Translit function |
471
|
|
|
* |
472
|
|
|
* @param string $str |
473
|
|
|
* @return string |
474
|
|
|
*/ |
475
|
|
|
public static function translit($str) { |
476
|
|
|
$rus = array('А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'); |
477
|
|
|
$lat = array('A', 'B', 'V', 'G', 'D', 'E', 'E', 'Gh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'Ch', 'Sh', 'Sch', 'Y', 'Y', 'Y', 'E', 'Yu', 'Ya', 'a', 'b', 'v', 'g', 'd', 'e', 'e', 'gh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'c', 'ch', 'sh', 'sch', 'y', 'y', 'y', 'e', 'yu', 'ya'); |
478
|
|
|
return str_replace($rus, $lat, $str); |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* get youtube video ID from URL |
483
|
|
|
* |
484
|
|
|
* @author http://stackoverflow.com/a/6556662 |
485
|
|
|
* @param string $url |
486
|
|
|
* @return string Youtube video id or FALSE if none found. |
487
|
|
|
*/ |
488
|
|
|
public static function youtubeIdFromUrl($url) { |
489
|
|
|
$pattern = '%^# Match any youtube URL |
490
|
|
|
(?:https?://)? # Optional scheme. Either http or https |
491
|
|
|
(?:www\.)? # Optional www subdomain |
492
|
|
|
(?: # Group host alternatives |
493
|
|
|
youtu\.be/ # Either youtu.be, |
494
|
|
|
| youtube\.com # or youtube.com |
495
|
|
|
(?: # Group path alternatives |
496
|
|
|
/embed/ # Either /embed/ |
497
|
|
|
| /v/ # or /v/ |
498
|
|
|
| /watch\?v= # or /watch\?v= |
499
|
|
|
) # End path alternatives. |
500
|
|
|
) # End host alternatives. |
501
|
|
|
([\w-]{10,12}) # Allow 10-12 for 11 char youtube id. |
502
|
|
|
$%x'; |
503
|
|
|
$result = preg_match($pattern, $url, $matches); |
504
|
|
|
if (false !== $result) { |
505
|
|
|
return $matches[1]; |
506
|
|
|
} |
507
|
|
|
return false; |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
/** |
511
|
|
|
* check array is associative |
512
|
|
|
* |
513
|
|
|
* @author http://stackoverflow.com/a/173479 |
514
|
|
|
* @param array $arr |
515
|
|
|
* @return boolean |
516
|
|
|
*/ |
517
|
|
|
public static function isAssoc(&$arr) { |
518
|
|
|
return array_keys($arr) !== range(0, count($arr) - 1); |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
public static function defValue(&$link, $defValue = '') { |
522
|
|
|
return isset($link) ? $link : $defValue; |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
public static function rusPrice($price, $zeroEnding = false) { |
|
|
|
|
526
|
|
|
$afterDot = $price == (int) $price ? 0 : 2; |
527
|
|
|
return number_format($price, $afterDot, '.', ' '); |
528
|
|
|
} |
529
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.