PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/protected/libs/tools/FileSystem.php

https://bitbucket.org/graaaf/erso
PHP | 231 lines | 156 code | 50 blank | 25 comment | 26 complexity | e1605fefec4c1da7e2d6f2303886a45a MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, LGPL-2.1, BSD-3-Clause, BSD-2-Clause
  1. <?php
  2. class FileSystem
  3. {
  4. const FILES_ICONS_DIR = '/images/icons/files/';
  5. const FILES_ICON_DEF = 'any.png';
  6. public static function getUniqFileName($file, $dir)
  7. {
  8. $dir = trim('/', $dir);
  9. if (mb_strpos($dir, $_SERVER['DOCUMENT_ROOT']) === false)
  10. {
  11. $dir = $_SERVER['DOCUMENT_ROOT'] . $dir . '/';
  12. }
  13. $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
  14. $name = md5(rand(0, getrandmax()) . uniqid("", true) . uniqid("", true) . $file) . '.' . $ext;
  15. if (file_exists($dir . $name))
  16. {
  17. self::getUniqFileName($name, $dir);
  18. }
  19. return $name;
  20. }
  21. public static function deleteDirRecursive($dir_name)
  22. {
  23. if (!is_dir($dir_name)) return false;
  24. $dir_handle = opendir($dir_name);
  25. if (!$dir_handle) return false;
  26. while(($file = readdir($dir_handle)) !== false)
  27. {
  28. if ($file == "." or $file == "..") continue;
  29. if (!is_dir($dir_name."/".$file))
  30. {
  31. unlink($dir_name."/".$file);
  32. }
  33. else
  34. {
  35. self::deleteDirRecursive($dir_name.'/'.$file);
  36. }
  37. }
  38. rmdir($dir_name);
  39. closedir($dir_handle);
  40. return true;
  41. }
  42. public static function findSimilarFiles($dir, $file)
  43. {
  44. $dir_files = scandir($dir);
  45. $similar_files = array();
  46. foreach ($dir_files as $dir_file)
  47. {
  48. if ($dir_file == '.' || $dir_file == '..' || $dir_file == $file) continue;
  49. if (strpos($dir_file, $file) !== false) $similar_files[] = $dir_file;
  50. }
  51. return $similar_files;
  52. }
  53. public static function deleteFileWithSimilarNames($dir, $file)
  54. {
  55. $files = array_merge(
  56. array($file),
  57. self::findSimilarFiles($dir, $file)
  58. );
  59. self::unlinkFiles($dir, $files);
  60. }
  61. public static function unlinkFiles($dir, $files)
  62. {
  63. foreach ($files as $file)
  64. {
  65. $file_path = $dir . $file;
  66. if (file_exists($file_path))
  67. {
  68. unlink($file_path);
  69. }
  70. }
  71. }
  72. public static function getFileIcon($file)
  73. {
  74. $files_icons_path = $_SERVER['DOCUMENT_ROOT'] . self::FILES_ICONS_DIR;
  75. if (!is_dir($files_icons_path))
  76. {
  77. return;
  78. }
  79. $icons = array();
  80. $icons_files = scandir($files_icons_path);
  81. foreach ($icons_files as $i => $icon_file)
  82. {
  83. if ($icon_file[0] == '.')
  84. {
  85. continue;
  86. }
  87. $icon_ext = str_replace('.' . pathinfo($icon_file, PATHINFO_EXTENSION), '', $icon_file);
  88. $icons[$icon_ext] = $icon_file;
  89. }
  90. $ext = pathinfo($file, PATHINFO_EXTENSION);
  91. if (isset($icons[$ext]))
  92. {
  93. return self::FILES_ICONS_DIR . $icons[$ext];
  94. }
  95. else
  96. {
  97. return self::FILES_ICONS_DIR . self::FILES_ICON_DEF;
  98. }
  99. }
  100. /************FileBalance***********/
  101. /**
  102. * Простой балансировщик файлов. Занимается равномерным распределением файлов по директориям.
  103. * Если в одной директории будет накапливаться слишком много файлов, то время поиска файла в этой директории
  104. * будет сильно расти.
  105. *
  106. * По умолчанию глубина вложенности подпапок $depth = 1
  107. * Для каждого файлы вызывается md5(uniqid(""))
  108. * из первых $depth*2 символов создает $depth двубуквенных директорий и файл перемещается туда .
  109. * За счет нормальности распределения md5(uniqid("")) файлы будут распределяться равномерно.
  110. * Получаем 256 возможных директорий, при количестве файлов в каждой
  111. * директории до 1000 файлов, не имеем проблем с производительностью.
  112. * Значит каждое хранилище(параметр $base_target_directory) обеспечивает быстрый доступ к 1/4 миллиона файлов.
  113. *
  114. * Накладные расходы:
  115. * EXT3 занимает 4КБ(служебной информации) на директорию.
  116. * Значит одно хранилище займет: 1мб при $depth = 1, 256мб при $depth = 2
  117. *
  118. * Возможный хранимый объем:
  119. * 1000 файлов по 1мб на директорию: 256ГБ при $depth = 1, 65ТБ при $depth = 2
  120. *
  121. * Устанавливать $depth больше 2-х не рекомендуется, сильно возрастают накладные расходы на хранение структуры каталогов.
  122. */
  123. public static $saveOriginalFileName = true;
  124. public static $depth = 1;
  125. public static function moveToVault($src_file, $base_vault_directory, $as_array = false)
  126. {
  127. if (!is_file($src_file))
  128. {
  129. return false;
  130. }
  131. list($target_path, $target_file) = self::getVaultPathAndName($src_file, $base_vault_directory);
  132. if (!is_dir('./' . $target_path))
  133. {
  134. @mkdir('./' . $target_path, 0755, true);
  135. }
  136. @rename('./' . $src_file, './' . $target_path . '/' . $target_file);
  137. if ($as_array)
  138. {
  139. return array(
  140. $target_path, $target_file
  141. );
  142. }
  143. else
  144. {
  145. return $target_path . '/' . $target_file;
  146. }
  147. }
  148. public static function getVaultPathAndName($src_file, $base_vault_directory, $target_file_name = null)
  149. {
  150. $id = md5(uniqid("", true));
  151. //from 4 symbol construct 2 folders
  152. $folder_id = substr($id, 0, self::$depth * 2);
  153. $folder_id = implode('/', str_split($folder_id, 2));
  154. //new file name
  155. if ($target_file_name === null)
  156. {
  157. if (self::$saveOriginalFileName)
  158. {
  159. $target_file_name = pathinfo($src_file, PATHINFO_BASENAME);
  160. }
  161. else
  162. {
  163. $target_file_name =
  164. substr($id, self::$depth * 2) . '.' . pathinfo($src_file, PATHINFO_EXTENSION);
  165. }
  166. }
  167. $target_path = $base_vault_directory . '/' . $folder_id;
  168. $target_file = self::vaultResolveCollision($target_path, $target_file_name);
  169. return array(
  170. $target_path, $target_file
  171. );
  172. }
  173. public static function vaultResolveCollision($path, $file)
  174. {
  175. while (is_file('./' . $path . '/' . $file))
  176. {
  177. $file = rand(0, 10) . $file;
  178. }
  179. return $file;
  180. }
  181. }