1
|
|
|
<?php |
|
|
|
|
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); |
|
|
|
|
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; |
|
|
|
|
107
|
|
|
} // Просто скопируем файл |
108
|
|
|
else if (is_file($path)) { |
109
|
|
|
// Если передана папка как новый файл - получим имя файла |
110
|
|
|
if (is_dir($dest)) $dest .= pathinfo($path, PATHINFO_FILENAME) . '.' . pathinfo($path, PATHINFO_EXTENSION); |
|
|
|
|
111
|
|
|
|
112
|
|
|
return copy($path, $dest); |
113
|
|
|
} // Выходим |
114
|
|
|
else return FALSE; |
|
|
|
|
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()) |
|
|
|
|
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) { |
|
|
|
|
134
|
|
|
unlink($file); |
135
|
1 |
|
} |
136
|
|
|
|
137
|
1 |
|
return TRUE; |
|
|
|
|
138
|
|
|
} // Если передан путь к файлу то просто удалим его |
139
|
|
|
else if (file_exists($path)) { |
140
|
|
|
unlink($path); |
141
|
|
|
return TRUE; |
|
|
|
|
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
return FALSE; |
|
|
|
|
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')) |
|
|
|
|
161
|
|
|
{ |
162
|
|
|
// Если установлено ограничение на глубину - выйдем |
163
|
7 |
|
if (isset($max_level) && $level > $max_level) return $result; |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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]; |
|
|
|
|
259
|
|
|
|
260
|
|
|
// Ничего не вышло =( |
261
|
|
|
return FALSE; |
|
|
|
|
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]; |
|
|
|
|
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
|
|
|
|
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.