Completed
Push — master ( b2aa64...db9a1b )
by Alexey
05:01
created

Tools::isAssoc()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
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
    {
24
        $charactersLength = strlen($characters);
25
        $randomString = '';
26
        for ($i = 0; $i < $length; $i++) {
27
            $randomString .= $characters[rand(0, $charactersLength - 1)];
28
        }
29
        return $randomString;
30
    }
31
32
    /**
33
     * Clean and return user query params
34
     * 
35
     * @param string $uri
36
     * @return array
37
     */
38
    public static function uriParse($uri)
39
    {
40
        $answerPos = strpos($uri, '?');
41
        $params = array_slice(explode('/', substr($uri, 0, $answerPos ? $answerPos : strlen($uri) )), 1);
42
43
        foreach ($params as $key => $param) {
44
            if ($param != '') {
45
                $params[$key] = urldecode($param);
46
            } else {
47
                unset($params[$key]);
48
            }
49
        }
50
        return $params;
51
    }
52
53
    /**
54
     * Recursive create dir
55
     * 
56
     * @param string $path
57
     * @return boolean
58
     */
59
    public static function createDir($path)
60
    {
61
        if (file_exists($path))
62
            return true;
63
64
        $path = explode('/', $path);
65
        $cur = '';
66
        foreach ($path as $item) {
67
            $cur .= $item . '/';
68
            if (!file_exists($cur)) {
69
                mkdir($cur);
70
            }
71
        }
72
        return true;
73
    }
74
75
    /**
76
     * Resize image in path
77
     * 
78
     * @param string $img_path
79
     * @param int $max_width
80
     * @param int $max_height
81
     * @param string|false $crop
82
     * @param string $pos
83
     * @return string
84
     */
85
    public static function resizeImage($img_path, $max_width = 1000, $max_height = 1000, $crop = false, $pos = 'center')
86
    {
87
        ini_set("gd.jpeg_ignore_warning", 1);
88
        list( $img_width, $img_height, $img_type, $img_tag ) = getimagesize($img_path);
89
        switch ($img_type) {
90
            case 1:
91
                $img_type = 'gif';
92
                break;
93
            case 3:
94
                $img_type = 'png';
95
                break;
96
            case 2:
97
            default:
98
                $img_type = 'jpeg';
99
                break;
100
        }
101
        $imagecreatefromX = "imagecreatefrom{$img_type}";
102
        $src_res = $imagecreatefromX($img_path);
103
104
        if ($img_width / $max_width > $img_height / $max_height)
105
            $separator = $img_width / $max_width;
106
        else
107
            $separator = $img_height / $max_height;
108
109
        if ($crop === true || $crop == 'q') {
110
            if ($img_width > $img_height) {
111
                $imgX = floor(( $img_width - $img_height ) / 2);
112
                $imgY = 0;
113
                $img_width = $img_height;
114
                $new_width = $max_width;
115
                $new_height = $max_height;
116 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
117
                $imgX = 0;
118
                $imgY = floor(( $img_height - $img_width ) / 2);
119
                $img_height = $img_width;
120
                $new_width = $max_width;
121
                $new_height = $max_height;
122
            }
123
            if ($pos == 'top') {
124
                $imgY = 0;
125
            }
126
        } elseif ($crop == 'c') {
127
//Вычисляем некий коэффициент масштабирования
128
            $k1 = $img_width / $max_width;
129
            $k2 = $img_height / $max_height;
130
            $k = $k1 > $k2 ? $k2 : $k1;
131
            $ow = $img_width;
132
            $oh = $img_height;
133
//Вычисляем размеры области для нового изображения
134
            $img_width = intval($max_width * $k);
135
            $img_height = intval($max_height * $k);
136
            $new_width = $max_width;
137
            $new_height = $max_height;
138
//Находим начальные координаты (центрируем новое изображение)
139
            $imgX = (int) (($ow / 2) - ($img_width / 2) );
140
            if ($pos == 'center') {
141
                $imgY = (int) (($oh / 2) - ($img_height / 2));
142
            } else {
143
                $imgY = 0;
144
            }
145 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
146
            $imgX = 0;
147
            $imgY = 0;
148
            $new_width = floor($img_width / $separator);
149
            $new_height = floor($img_height / $separator);
150
        }
151
152
        $new_res = imagecreatetruecolor($new_width, $new_height);
153
        imageAlphaBlending($new_res, false);
154
        imagesavealpha($new_res, true);
155
        imagecopyresampled($new_res, $src_res, 0, 0, $imgX, $imgY, $new_width, $new_height, $img_width, $img_height);
156
157
        if ($img_type == 'jpeg') {
158
            imageinterlace($new_res, 1); // чересстрочное формирование изображение
159
            imagejpeg($new_res, $img_path, 85);
160
        } else {
161
            $imageX = "image{$img_type}";
162
            $imageX($new_res, $img_path);
163
        }
164
165
        imagedestroy($new_res);
166
        imagedestroy($src_res);
167
        return $img_type;
168
    }
169
170
    /**
171
     * Send mail
172
     * 
173
     * @param string $from
174
     * @param string $to
175
     * @param string $subject
176
     * @param string $text
177
     * @param string $charset
178
     * @param string $ctype
179
     * @return boolean
180
     */
181
    public static function sendMail($from, $to, $subject, $text, $charset = 'utf-8', $ctype = 'text/html')
182
    {
183
        $headers = "From: {$from}\r\n";
184
        $headers .= "Content-type: {$ctype}; charset={$charset}\r\n";
185
        $headers .= "Mime-Version: 1.0\r\n";
186
        return mail($to, $subject, $text, $headers);
187
    }
188
189
    /**
190
     * Redirect user from any place of code
191
     * 
192
     * Also add message to message query for view
193
     * 
194
     * @param string $href
195
     * @param string $text
196
     * @param string $status
197
     */
198
    public static function redirect($href = null, $text = false, $status = 'info')
1 ignored issue
show
Coding Style introduced by
redirect uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
199
    {
200
        if ($href === null) {
201
            $href = $_SERVER['REQUEST_URI'];
202
        }
203
        if ($text !== false) {
204
            Msg::add($text, $status);
205
        }
206
        if (!headers_sent()) {
207
            header("Location: {$href}");
208
        } else {
209
            echo '\'"><script>window.location="' . $href . '";</script>';
210
        }
211
        exit("Перенаправление на: <a href = '{$href}'>{$href}</a>");
212
    }
213
214
    /**
215
     * Функция возвращает окончание для множественного числа слова на основании числа и массива окончаний
216
     * @param  $number Integer Число на основе которого нужно сформировать окончание
217
     * @param  $endingsArray  Array Массив слов или окончаний для чисел (1, 4, 5),
218
     *         например array('яблоко', 'яблока', 'яблок')
219
     * @return String
220
     */
221
    public static function getNumEnding($number, $endingArray)
222
    {
223
        $number = $number % 100;
224
        if ($number >= 11 && $number <= 19) {
225
            $ending = $endingArray[2];
226
        } else {
227
            $i = $number % 10;
228
            switch ($i) {
229
                case (1): $ending = $endingArray[0];
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
230
                    break;
231
                case (2):
232
                case (3):
233
                case (4): $ending = $endingArray[1];
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
234
                    break;
235
                default: $ending = $endingArray[2];
0 ignored issues
show
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
236
            }
237
        }
238
        return $ending;
239
    }
240
241
    /**
242
     * Clean request path
243
     * 
244
     * @param string $path
245
     * @return string
246
     */
247
    public static function parsePath($path)
248
    {
249
        $path = str_replace('\\', '/', $path);
250
        $pathArray = explode('/', $path);
251
        $cleanPathArray = [];
252
        do {
253
            $changes = 0;
254
            foreach ($pathArray as $pathItem) {
255
                if (trim($pathItem) === '' || $pathItem == '.') {
256
                    $changes++;
257
                    continue;
258
                }
259
                if ($pathItem == '..') {
260
                    array_pop($cleanPathArray);
261
                    $changes++;
262
                    continue;
263
                }
264
                $cleanPathArray[] = $pathItem;
265
            }
266
            $pathArray = $cleanPathArray;
267
            $cleanPathArray = [];
268
        } while ($changes);
269
        return (strpos($path, '/') === 0 ? '/' : '') . implode('/', $pathArray);
270
    }
271
272
    /**
273
     * Show date in rus
274
     * 
275
     * @param string $date
276
     * @return string
277
     */
278
    public static function toRusDate($date)
279
    {
280
        $yy = (int) substr($date, 0, 4);
281
        $mm = (int) substr($date, 5, 2);
282
        $dd = (int) substr($date, 8, 2);
283
284
        $hours = substr($date, 11, 5);
285
286
        $month = array('января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря');
287
        if (empty($month[$mm - 1])) {
288
            return 'Не указано';
289
        }
290
        return ($dd > 0 ? $dd . " " : '') . $month[$mm - 1] . " " . $yy . " " . $hours;
291
    }
292
293
    /**
294
     * Set header
295
     * 
296
     * @param string $code
297
     * @param boolean $exit
298
     */
299
    public static function header($code, $exit = false)
300
    {
301
        if (!headers_sent()) {
302
            switch ($code) {
303
                case '404':
304
                    header('HTTP/1.1 404 Not Found');
305
                    break;
306
                default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
307
                    header($code);
308
            }
309
        }
310
        if ($exit) {
311
            exit;
312
        }
313
    }
314
315
    /**
316
     * Return exist path from array
317
     * 
318
     * If no exist path in array - return default
319
     * 
320
     * @param array $paths
321
     * @param string|false $default
322
     * @return string|false
323
     */
324
    public static function pathsResolve($paths = [], $default = false)
325
    {
326
        foreach ($paths as $path) {
327
            if (file_exists($path)) {
328
                return $path;
329
            }
330
        }
331
        return $default;
332
    }
333
334
    /**
335
     * Convert acronyms to bites
336
     * 
337
     * @param string $val
338
     * @return int
339
     */
340
    public static function toBytes($val)
341
    {
342
        $val = trim($val);
343
        $last = strtolower($val[strlen($val) - 1]);
344
        switch ($last) {
345
            case 'g':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
346
                $val *= 1024;
347
            case 'm':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
348
                $val *= 1024;
349
            case 'k':
350
                $val *= 1024;
351
        }
352
353
        return $val;
354
    }
355
356
    /**
357
     * Recursive copy directories and files
358
     * 
359
     * @param string $from
360
     * @param string $to
361
     */
362
    public static function copyFiles($from, $to)
363
    {
364
        $from = rtrim($from, '/');
365
        $to = rtrim($to, '/');
366
        self::createDir($to);
367
        $files = scandir($from);
368
        foreach ($files as $file) {
369
            if (in_array($file, ['.', '..'])) {
370
                continue;
371
            }
372
            if (is_dir($from . '/' . $file)) {
373
                self::copyFiles($from . '/' . $file, $to . '/' . $file);
374
            } else {
375
                copy($from . '/' . $file, $to . '/' . $file);
376
            }
377
        }
378
    }
379
380
    /**
381
     * Translit function
382
     * 
383
     * @param string $str
384
     * @return string
385
     */
386
    public static function translit($str)
387
    {
388
        $rus = array('А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я');
389
        $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');
390
        return str_replace($rus, $lat, $str);
391
    }
392
393
    /**
394
     * get youtube video ID from URL
395
     *
396
     * @author http://stackoverflow.com/a/6556662
397
     * @param string $url
398
     * @return string Youtube video id or FALSE if none found. 
399
     */
400
    public static function youtubeIdFromUrl($url)
401
    {
402
        $pattern = '%^# Match any youtube URL
403
        (?:https?://)?  # Optional scheme. Either http or https
404
        (?:www\.)?      # Optional www subdomain
405
        (?:             # Group host alternatives
406
          youtu\.be/    # Either youtu.be,
407
        | youtube\.com  # or youtube.com
408
          (?:           # Group path alternatives
409
            /embed/     # Either /embed/
410
          | /v/         # or /v/
411
          | /watch\?v=  # or /watch\?v=
412
          )             # End path alternatives.
413
        )               # End host alternatives.
414
        ([\w-]{10,12})  # Allow 10-12 for 11 char youtube id.
415
        $%x'
416
        ;
417
        $result = preg_match($pattern, $url, $matches);
418
        if (false !== $result) {
419
            return $matches[1];
420
        }
421
        return false;
422
    }
423
424
    /**
425
     * check array is associative
426
     *
427
     * @author http://stackoverflow.com/a/173479
428
     * @param array $arr
429
     * @return boolean
430
     */
431
    public static function isAssoc(&$arr)
432
    {
433
        return array_keys($arr) !== range(0, count($arr) - 1);
434
    }
435
436
}
437