Test Failed
Push — master ( 310ecf...5d6054 )
by Alexey
05:08
created

Tools::delDir()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
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
        $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
        $path = explode('/', $path);
62
        $cur = '';
63
        foreach ($path as $item) {
64
            $cur .= $item . '/';
65
            if (!file_exists($cur)) {
66
                mkdir($cur);
67
            }
68
        }
69
        return true;
70
    }
71
72
    public static function delDir($dir) {
73
        $files = array_diff(scandir($dir), array('.', '..'));
74
        foreach ($files as $file) {
75
            is_dir("$dir/$file") ? delTree("$dir/$file") : unlink("$dir/$file");
76
        }
77
        return rmdir($dir);
78
    }
79
80
    /**
81
     * Resize image in path
82
     * 
83
     * @param string $img_path
84
     * @param int $max_width
85
     * @param int $max_height
86
     * @param string|false $crop
87
     * @param string $pos
88
     * @return string
89
     */
90
    public static function resizeImage($img_path, $max_width = 1000, $max_height = 1000, $crop = false, $pos = 'center') {
91
        ini_set("gd.jpeg_ignore_warning", 1);
92
        list($img_width, $img_height, $img_type, $img_tag) = getimagesize($img_path);
93
        switch ($img_type) {
94
            case 1:
95
                $img_type = 'gif';
96
                break;
97
            case 3:
98
                $img_type = 'png';
99
                break;
100
            case 2:
101
            default:
102
                $img_type = 'jpeg';
103
                break;
104
        }
105
        $imagecreatefromX = "imagecreatefrom{$img_type}";
106
        $src_res = $imagecreatefromX($img_path);
107
        if (!$src_res) {
108
            return false;
109
        }
110
111
        if ($img_width / $max_width > $img_height / $max_height) {
112
            $separator = $img_width / $max_width;
113
        } else {
114
            $separator = $img_height / $max_height;
115
        }
116
117
        if ($crop === true || $crop == 'q') {
118
            if ($img_width > $img_height) {
119
                $imgX = floor(($img_width - $img_height) / 2);
120
                $imgY = 0;
121
                $img_width = $img_height;
122
                $new_width = $max_width;
123
                $new_height = $max_height;
124 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...
125
                $imgX = 0;
126
                $imgY = floor(($img_height - $img_width) / 2);
127
                $img_height = $img_width;
128
                $new_width = $max_width;
129
                $new_height = $max_height;
130
            }
131
            if ($pos == 'top') {
132
                $imgY = 0;
133
            }
134
        } elseif ($crop == 'c') {
135
//Вычисляем некий коэффициент масштабирования
136
            $k1 = $img_width / $max_width;
137
            $k2 = $img_height / $max_height;
138
            $k = $k1 > $k2 ? $k2 : $k1;
139
            $ow = $img_width;
140
            $oh = $img_height;
141
//Вычисляем размеры области для нового изображения
142
            $img_width = intval($max_width * $k);
143
            $img_height = intval($max_height * $k);
144
            $new_width = $max_width;
145
            $new_height = $max_height;
146
//Находим начальные координаты (центрируем новое изображение)
147
            $imgX = (int) (($ow / 2) - ($img_width / 2));
148
            if ($pos == 'center') {
149
                $imgY = (int) (($oh / 2) - ($img_height / 2));
150
            } else {
151
                $imgY = 0;
152
            }
153 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...
154
            $imgX = 0;
155
            $imgY = 0;
156
            $new_width = floor($img_width / $separator);
157
            $new_height = floor($img_height / $separator);
158
        }
159
160
        $new_res = imagecreatetruecolor($new_width, $new_height);
161
        imageAlphaBlending($new_res, false);
162
        imagesavealpha($new_res, true);
163
        imagecopyresampled($new_res, $src_res, 0, 0, $imgX, $imgY, $new_width, $new_height, $img_width, $img_height);
164
165
        if ($img_type == 'jpeg') {
166
            imageinterlace($new_res, 1); // чересстрочное формирование изображение
167
            imagejpeg($new_res, $img_path, 85);
168
        } else {
169
            $imageX = "image{$img_type}";
170
            $imageX($new_res, $img_path);
171
        }
172
173
        imagedestroy($new_res);
174
        imagedestroy($src_res);
175
        return $img_type;
176
    }
177
178
    /**
179
     * Send mail
180
     * 
181
     * @param string $from
182
     * @param string $to
183
     * @param string $subject
184
     * @param string $text
185
     * @param string $charset
186
     * @param string $ctype
187
     * @return boolean
188
     */
189
    public static function sendMail($from, $to, $subject, $text, $charset = 'utf-8', $ctype = 'text/html') {
190
        $msg = compact('from', 'to', 'subject', 'text', 'charset', 'ctype');
191
        $msg = Inji::$inst->event('sendMail', $msg);
192
        if (is_array($msg)) {
193
            $headers = "From: {$msg['from']}\r\n";
194
            $headers .= "Content-type: {$msg['ctype']}; charset={$msg['charset']}\r\n";
195
            $headers .= "Mime-Version: 1.0\r\n";
196
            return mail($msg['to'], $msg['subject'], $msg['text'], $headers);
197
        }
198
        return $msg;
199
    }
200
201
    /**
202
     * Redirect user from any place of code
203
     * 
204
     * Also add message to message query for view
205
     * 
206
     * @param string $href
207
     * @param string $text
208
     * @param string $status
209
     */
210
    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...
211
        if ($href === null) {
212
            $href = $_SERVER['REQUEST_URI'];
213
        }
214
        if ($text !== false) {
215
            Msg::add($text, $status);
216
        }
217
        if (!headers_sent()) {
218
            header("Location: {$href}");
219
        } else {
220
            echo '\'"><script>window.location="' . $href . '";</script>';
221
        }
222
        exit("Перенаправление на: <a href = '{$href}'>{$href}</a>");
223
    }
224
225
    /**
226
     * Функция возвращает окончание для множественного числа слова на основании числа и массива окончаний
227
     * @param  Integer $number  Число на основе которого нужно сформировать окончание
228
     * @param  String[] $endingsArray  Массив слов или окончаний для чисел (1, 4, 5),
0 ignored issues
show
Documentation introduced by
There is no parameter named $endingsArray. Did you maybe mean $endingArray?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
229
     *         например ['яблоко', 'яблока', 'яблок']
230
     * @return String
231
     */
232
    public static function getNumEnding($number, $endingArray) {
233
        $number = $number % 100;
234
        if ($number >= 11 && $number <= 19) {
235
            $ending = $endingArray[2];
236
        } else {
237
            $i = $number % 10;
238
            switch ($i) {
239
                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...
240
                    break;
241
                case (2):
242
                case (3):
243
                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...
244
                    break;
245
                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...
246
            }
247
        }
248
        return $ending;
249
    }
250
251
    /**
252
     * Clean request path
253
     * 
254
     * @param string $path
255
     * @return string
256
     */
257
    public static function parsePath($path) {
258
        $path = str_replace('\\', '/', $path);
259
        $pathArray = explode('/', $path);
260
        $cleanPathArray = [];
261
        do {
262
            $changes = 0;
263
            foreach ($pathArray as $pathItem) {
264
                if (trim($pathItem) === '' || $pathItem == '.') {
265
                    $changes++;
266
                    continue;
267
                }
268
                if ($pathItem == '..') {
269
                    array_pop($cleanPathArray);
270
                    $changes++;
271
                    continue;
272
                }
273
                $cleanPathArray[] = $pathItem;
274
            }
275
            $pathArray = $cleanPathArray;
276
            $cleanPathArray = [];
277
        } while ($changes);
278
        return (strpos($path, '/') === 0 ? '/' : '') . implode('/', $pathArray);
279
    }
280
281
    /**
282
     * Show date in rus
283
     * 
284
     * @param string $date
285
     * @return string
286
     */
287
    public static function toRusDate($date) {
288
        $yy = (int) substr($date, 0, 4);
289
        $mm = (int) substr($date, 5, 2);
290
        $dd = (int) substr($date, 8, 2);
291
292
        $hours = substr($date, 11, 5);
293
294
        $month = array('января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря');
295
        if (empty($month[$mm - 1])) {
296
            return 'Не указано';
297
        }
298
        return ($dd > 0 ? $dd . " " : '') . $month[$mm - 1] . " " . $yy . " " . $hours;
299
    }
300
301
    /**
302
     * Set header
303
     * 
304
     * @param string $code
305
     * @param boolean $exit
306
     */
307
    public static function header($code, $exit = false) {
308
        if (!headers_sent()) {
309
            switch ($code) {
310
                case '404':
311
                    header('HTTP/1.1 404 Not Found');
312
                    break;
313
                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...
314
                    header($code);
315
            }
316
        }
317
        if ($exit) {
318
            exit;
319
        }
320
    }
321
322
    /**
323
     * Return exist path from array
324
     * 
325
     * If no exist path in array - return default
326
     * 
327
     * @param array $paths
328
     * @param string|false $default
329
     * @return string|false
330
     */
331
    public static function pathsResolve($paths = [], $default = false) {
332
        foreach ($paths as $path) {
333
            if (file_exists($path)) {
334
                return $path;
335
            }
336
        }
337
        return $default;
338
    }
339
340
    /**
341
     * Convert acronyms to bites
342
     * 
343
     * @param string $val
344
     * @return int
345
     */
346
    public static function toBytes($val) {
347
        $val = trim($val);
348
        $last = strtolower($val[strlen($val) - 1]);
349
        switch ($last) {
350
            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...
351
                $val *= 1024;
352
            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...
353
                $val *= 1024;
354
            case 'k':
355
                $val *= 1024;
356
        }
357
358
        return $val;
359
    }
360
361
    /**
362
     * Recursive copy directories and files
363
     * 
364
     * @param string $from
365
     * @param string $to
366
     */
367
    public static function copyFiles($from, $to) {
368
        $from = rtrim($from, '/');
369
        $to = rtrim($to, '/');
370
        self::createDir($to);
371
        $files = scandir($from);
372
        foreach ($files as $file) {
373
            if (in_array($file, ['.', '..'])) {
374
                continue;
375
            }
376
            if (is_dir($from . '/' . $file)) {
377
                self::copyFiles($from . '/' . $file, $to . '/' . $file);
378
            } else {
379
                copy($from . '/' . $file, $to . '/' . $file);
380
            }
381
        }
382
    }
383
384
    /**
385
     * Translit function
386
     * 
387
     * @param string $str
388
     * @return string
389
     */
390
    public static function translit($str) {
391
        $rus = array('А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я');
392
        $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');
393
        return str_replace($rus, $lat, $str);
394
    }
395
396
    /**
397
     * get youtube video ID from URL
398
     *
399
     * @author http://stackoverflow.com/a/6556662
400
     * @param string $url
401
     * @return string Youtube video id or FALSE if none found. 
402
     */
403
    public static function youtubeIdFromUrl($url) {
404
        $pattern = '%^# Match any youtube URL
405
        (?:https?://)?  # Optional scheme. Either http or https
406
        (?:www\.)?      # Optional www subdomain
407
        (?:             # Group host alternatives
408
          youtu\.be/    # Either youtu.be,
409
        | youtube\.com  # or youtube.com
410
          (?:           # Group path alternatives
411
            /embed/     # Either /embed/
412
          | /v/         # or /v/
413
          | /watch\?v=  # or /watch\?v=
414
          )             # End path alternatives.
415
        )               # End host alternatives.
416
        ([\w-]{10,12})  # Allow 10-12 for 11 char youtube id.
417
        $%x'
418
        ;
419
        $result = preg_match($pattern, $url, $matches);
420
        if (false !== $result) {
421
            return $matches[1];
422
        }
423
        return false;
424
    }
425
426
    /**
427
     * check array is associative
428
     *
429
     * @author http://stackoverflow.com/a/173479
430
     * @param array $arr
431
     * @return boolean
432
     */
433
    public static function isAssoc(&$arr) {
434
        return array_keys($arr) !== range(0, count($arr) - 1);
435
    }
436
}