File   B
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 0

Test Coverage

Coverage 44%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 37
c 1
b 0
f 0
lcom 3
cbo 0
dl 0
loc 289
ccs 33
cts 75
cp 0.44
rs 8.6

8 Methods

Rating   Name   Duplication   Size   Complexity  
A clear() 0 18 4
C dir() 0 58 18
A mkdir() 0 18 3
A getExtension() 0 8 2
A find() 0 4 1
B copy() 0 38 6
A getMIME() 0 11 2
A isImage() 0 8 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 10 and the first side effect is on line 301.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
namespace samson\core;
3
4
// TODO: Should separated to external module
5
6
/**
7
 * Общие методы для работы с файлами и каталогами
8
 * @author Vitaly Iegorov <[email protected]>
9
 */
10
class File
11
{
12
	/**
13
	 * Коллекция связей между MIME-type и расширениями файлов
14
	 * @var array
15
	 */
16
	public static $MIMEExtension = array
17
	(
18
        'text/css' => 'css',
19
        'application/x-font-woff' => 'woff',
20
        'application/x-javascript' => 'js',
21
        'text/html;charset=utf-8' => 'htm',
22
        'text/x-component' => 'htc',
23
        'image/jpeg' => 'jpg',
24
        'image/pjpeg' => 'jpg',
25
        'image/png' => 'png',
26
        'image/x-png' => 'png',
27
        'image/jpg' => 'jpg',
28
        'image/gif' => 'gif',
29
        'text/plain' => 'txt',
30
        'application/pdf' => 'pdf',
31
        'application/zip' => 'zip',
32
        'application/rtf' => 'rtf',
33
        'application/msword' => 'doc',
34
        'application/msexcel' => 'xls',
35
        'application/vnd.ms-excel' => 'xls',
36
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
37
		'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
38
        'application/octet-stream' => 'sql',
39
        'audio/mpeg' => 'mp3'
40
    );
41
42
	/**
43
     * Коллекция связей между расширениями файлов и их MIME-type
44
	 * @var array
45
	 */
46
	public static $ExtensionMIME = array();
47
48
	/**
49
	 * Коллекция расширений файлов которые являются картинками
50
	 * @var array
51
	 */
52
	public static $ImageExtension = array
53
	(
54
        'jpg' => 'jpg',
55
        'jpeg' => 'jpeg',
56
        'png' => 'png',
57
        'jpg' => 'jpg',
58
        'gif' => 'gif'
59
    );
60
61
	/**
62
	 * Проверить существует ли файл по указанному пути
63
	 *
64
	 * @param string $path Путь к файлу
65
	 * @param string $file Имя файла для поиска
66
	 */
67
    public static function find($path, $file)
68
    {
69
        return file_exists($path . '/' . $file);
70
    }
71
72
    /**
73
     * Скопировать файлы и папки используя рекурсивный перебор
74
     *
75
     * @param string $path Путь к источнику для копирования
76
     * @param string $dest Путь к месту куда необходимо выполнить копирование
77
     */
78
    public static function copy($path, $dest)
79
    {
80
		// Если это папка
81
        if (is_dir($path)) {
82
			// Создадим папку в том месте куда нужно копировать, если её там нет
83
            if (!file_exists($dest)) mkdir($dest, 0755, TRUE);
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected true, but found TRUE.
Loading history...
84
85
			// Получим содержание текущей папки
86
            $files = scandir($path);
87
88
			// Получим количетсво файлов в папке
89
            $files_count = sizeof($files);
90
91
			// Переберем полученные файлы
92
            for ($i = 2; $i < $files_count; $i++) {
93
				// Получим имя текущего файла
94
                $file = &$files[$i];
95
96
				// Получим полный путь к файлу источнику
97
                $source_path = $path . '/' . $file;
98
99
				// Получим полный путь к новому файлу
100
                $dest_path = $dest . '/' . $file;
101
102
				// Углубимся в рекурсию
103
                self::copy($source_path, $dest_path);
104
			}
105
106
			return TRUE;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected true, but found TRUE.
Loading history...
107
        } // Просто скопируем файл
108
        else if (is_file($path)) {
109
			// Если передана папка как новый файл - получим имя файла
110
            if (is_dir($dest)) $dest .= pathinfo($path, PATHINFO_FILENAME) . '.' . pathinfo($path, PATHINFO_EXTENSION);
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
111
112
            return copy($path, $dest);
113
        } // Выходим
114
        else return FALSE;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected false, but found FALSE.
Loading history...
115
    }
116
117
    /**
118
     * Очистить путь
119
     * Если передан путь к папке то очистим все её файлы(содержимое)
120
     * Если передан путь к файлу то удали его
121
     *
122
     * @param string $path          Путь к удаляемому ресурсу
123
     * @param array  $type          Collection of file extensions for ignoring
124
     * @param array  $ignoreFolders Collection of folders for ignoring
125
     *
126
     * @return boolean / FALSE
127
     */
128 1
    public static function clear($path, $type = NULL, $ignoreFolders = array())
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
129
    {
130
        // Если передан путь к папке то удалим все файлы в ней
131 1
        if (is_dir($path)) {
132 1
            $files = array();
133 1
            foreach (self::dir($path, $type, '', $files, null, 0, $ignoreFolders) as $file) {
0 ignored issues
show
Bug introduced by
It seems like $type defined by parameter $type on line 128 can also be of type array; however, samson\core\File::dir() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
134
                unlink($file);
135 1
            }
136
137 1
            return TRUE;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected true, but found TRUE.
Loading history...
138
        } // Если передан путь к файлу то просто удалим его
139
        else if (file_exists($path)) {
140
            unlink($path);
141
            return TRUE;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected true, but found TRUE.
Loading history...
142
		}
143
144
        return FALSE;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected false, but found FALSE.
Loading history...
145
    }
146
147
	/**
148
	 * Получить список файлов каталога
149
     *
150
     * @param string  $path      Путь к каталогу
151
     * @param string  $type      Фильтр для типа собираемых файлов
152
     * @param array   $result    Результат работі рекурсивной функции
153
     * @param string  $modifier  Модификатор пути к файлам для изменения их пути
154
     * @param string  $max_level Максимальная глубина работы метода
155
     * @param integer $level     Текщий уровень рекурсии
156
     * @param array   $restrict  Коллекция папок которые необходимо пропускать
157
     *
158
	 * @return array Коллекция файлов в каталоге
159
	 */
160 7
    public static function dir($path, $type = null, $modifier = '', & $result = array(), $max_level = NULL, $level = 0, $restrict = array('.git', '.svn', '.hg', '.settings'))
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
161
	{
162
		// Если установлено ограничение на глубину - выйдем
163 7
        if (isset($max_level) && $level > $max_level) return $result;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
164
165
        // If type filter is passed make it array anyway
166 7
        if (isset($type) && !is_array($type)) {
167 7
            $type = array($type);
168 7
        }
169
170
		// Откроем папку
171 7
        if (file_exists($path) && $handle = opendir($path)) {
172
			/* Именно этот способ чтения элементов каталога является правильным. */
173 7
            while (false !== ($entry = readdir($handle))) {
174
				// Ignore root paths
175 7
				if ($entry == '..' || $entry == '.') {
176 7
                    continue;
177
                }
178
179
                // Build full REAL path to entry
180 7
                $full_path = realpath($path . '/' . $entry);
181
182 7
                if (is_file($full_path)) {
183
                    // Check file type if ty filter is passed
184 7
                    if (!isset($type) || in_array(pathinfo($full_path, PATHINFO_EXTENSION), $type)) {
185 7
                        $result[] = normalizepath($modifier . $full_path);
186 7
                    }
187 7
                } else if (is_dir($full_path)) {
188
                    // Define if current path is not restricted
189 7
                    $ignored = false;
190
                    // Iterate all restrictions
191 7
                    foreach ($restrict as $ignore) {
192
                        // Try to find ignored path pattern in full path and store it to ignored flag
193
                        if (($ignored = ($ignore == $full_path)) !== false) {
194
                            // This is ignored path - break, ignored now is false(0)
195
                            break;
196
                        }
197 7
                    }
198
199
                    // If this path is not restricted
200 7
                    if ($ignored === false) {
201
                        // Go deeper in recursion
202 7
                        self::dir($full_path, $type, $modifier, $result, $max_level, ++$level, $restrict);
0 ignored issues
show
Bug introduced by
It seems like $type defined by array($type) on line 167 can also be of type array; however, samson\core\File::dir() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
203 7
                    }
204 7
                }
205 7
			}
206
207
			// Закроем чтение папки
208 7
			closedir($handle);
209 7
		}
210
		//else return e( 'Ошибка открытия папки(##)', E_SAMSON_CORE_ERROR, array( $path ) );
211
212
		// Сортируем
213 7
        if (sizeof($result)) sort($result);
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
214
215
		// Соберем массив в строку
216 7
		return $result;
217
	}
218
219
	/**
220
     * Create folder, method use recursive approach for creating if
221
     * "folder/folder/.." is passed.
222
     *
223
     * @param string $path  Folder path
224
     * @param string $group Folder group(www-data)
225
     * @param int    $mode  Folder mode(0775)
226
     *
227
     * @return int 1 - success, 0 - folder exists, -1 - errors
228
     */
229
    public static function mkdir($path, $group = 'www-data', $mode = 0775)
230
    {
231
        // If folder does not exists
232
        if (!file_exists($path)) {
233
            // Create folder with correct mode
234
            if (mkdir($path, $mode, true)) {
235
                // Change folder group
236
                @chgrp($path, $group);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
237
238
                return true;
239
            } else {
240
                return -1;
241
            }
242
        }
243
244
        // Folder already exists
245
        return false;
246
    }
247
248
    /**
249
     * Определить расширение файла по его MIME типу
250
     *
251
     * @param string $mime_type MIME тип файла
252
     *
253
     * @return string Расширение файла
254
     */
255
    public static function getExtension($mime_type)
256
    {
257
		// Обработаем тип получаемого файла и вернем его расширение если файл поддерживается
258
        if (isset(self::$MIMEExtension[$mime_type])) return self::$MIMEExtension[$mime_type];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
259
260
		// Ничего не вышло =(
261
		return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return FALSE; (false) is incompatible with the return type documented by samson\core\File::getExtension of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected false, but found FALSE.
Loading history...
262
	}
263
264
	/**
265
     * Определить MIME тип файла по его расширению
266
	 *
267
	 * @param string $path Путь к файлу или его имя
268
     *
269
	 * @return string MIME тип файла
270
	 */
271
    public static function getMIME($path)
272
	{
273
		// Получим расширение файла
274
        $file_ext = pathinfo($path, PATHINFO_EXTENSION);
275
276
		// Обработаем тип получаемого файла и вернем его расширение если файл поддерживается
277
        if (isset(self::$ExtensionMIME[$file_ext])) return self::$ExtensionMIME[$file_ext];
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
278
279
		// Ничего не вышло =(
280
		return 'application/octet-stream';
281
	}
282
283
    /**
284
	 * Определить является ли указанный файл картинкой
285
	 *
286
	 * @param string $path Путь к файлу или его имя
287
     *
288
	 * @return boolean Является ли данный файл картинкой
289
	 */
290
    public static function isImage($path)
291
	{
292
		// Получим расширение файла - всегда берем первые 3 символа
293
        $file_ext = trim(substr(pathinfo($path, PATHINFO_EXTENSION), 0, 3));
294
295
		// Проверим является ли расширение файла картинкой
296
        return isset(self::$ImageExtension[$file_ext]);
297
	}
298
}
299
300
// Сформируем обратный массив связей между расширением файла и его MIME-type
301
File::$ExtensionMIME = array_flip( File::$MIMEExtension );
302