FSTools.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. /**
  3. * Filesystem tools not provided by default; can recursively create, copy
  4. * and delete folders. Some template methods are provided for extensibility.
  5. *
  6. * @note This class must be instantiated to be used, although it does
  7. * not maintain state.
  8. */
  9. class FSTools
  10. {
  11. private static $singleton;
  12. /**
  13. * Returns a global instance of FSTools
  14. */
  15. public static function singleton()
  16. {
  17. if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools();
  18. return FSTools::$singleton;
  19. }
  20. /**
  21. * Sets our global singleton to something else; useful for overloading
  22. * functions.
  23. */
  24. public static function setSingleton($singleton)
  25. {
  26. FSTools::$singleton = $singleton;
  27. }
  28. /**
  29. * Recursively creates a directory
  30. * @param string $folder Name of folder to create
  31. * @note Adapted from the PHP manual comment 76612
  32. */
  33. public function mkdirr($folder)
  34. {
  35. $folders = preg_split("#[\\\\/]#", $folder);
  36. $base = '';
  37. for($i = 0, $c = count($folders); $i < $c; $i++) {
  38. if(empty($folders[$i])) {
  39. if (!$i) {
  40. // special case for root level
  41. $base .= DIRECTORY_SEPARATOR;
  42. }
  43. continue;
  44. }
  45. $base .= $folders[$i];
  46. if(!is_dir($base)){
  47. $this->mkdir($base);
  48. }
  49. $base .= DIRECTORY_SEPARATOR;
  50. }
  51. }
  52. /**
  53. * Copy a file, or recursively copy a folder and its contents; modified
  54. * so that copied files, if PHP, have includes removed
  55. * @note Adapted from http://aidanlister.com/repos/v/function.copyr.php
  56. */
  57. public function copyr($source, $dest)
  58. {
  59. // Simple copy for a file
  60. if (is_file($source)) {
  61. return $this->copy($source, $dest);
  62. }
  63. // Make destination directory
  64. if (!is_dir($dest)) {
  65. $this->mkdir($dest);
  66. }
  67. // Loop through the folder
  68. $dir = $this->dir($source);
  69. while ( false !== ($entry = $dir->read()) ) {
  70. // Skip pointers
  71. if ($entry == '.' || $entry == '..') {
  72. continue;
  73. }
  74. if (!$this->copyable($entry)) {
  75. continue;
  76. }
  77. // Deep copy directories
  78. if ($dest !== "$source/$entry") {
  79. $this->copyr("$source/$entry", "$dest/$entry");
  80. }
  81. }
  82. // Clean up
  83. $dir->close();
  84. return true;
  85. }
  86. /**
  87. * Overloadable function that tests a filename for copyability. By
  88. * default, everything should be copied; you can restrict things to
  89. * ignore hidden files, unreadable files, etc. This function
  90. * applies to copyr().
  91. */
  92. public function copyable($file)
  93. {
  94. return true;
  95. }
  96. /**
  97. * Delete a file, or a folder and its contents
  98. * @note Adapted from http://aidanlister.com/repos/v/function.rmdirr.php
  99. */
  100. public function rmdirr($dirname)
  101. {
  102. // Sanity check
  103. if (!$this->file_exists($dirname)) {
  104. return false;
  105. }
  106. // Simple delete for a file
  107. if ($this->is_file($dirname) || $this->is_link($dirname)) {
  108. return $this->unlink($dirname);
  109. }
  110. // Loop through the folder
  111. $dir = $this->dir($dirname);
  112. while (false !== $entry = $dir->read()) {
  113. // Skip pointers
  114. if ($entry == '.' || $entry == '..') {
  115. continue;
  116. }
  117. // Recurse
  118. $this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
  119. }
  120. // Clean up
  121. $dir->close();
  122. return $this->rmdir($dirname);
  123. }
  124. /**
  125. * Recursively globs a directory.
  126. */
  127. public function globr($dir, $pattern, $flags = NULL)
  128. {
  129. $files = $this->glob("$dir/$pattern", $flags);
  130. if ($files === false) $files = array();
  131. $sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR);
  132. if ($sub_dirs === false) $sub_dirs = array();
  133. foreach ($sub_dirs as $sub_dir) {
  134. $sub_files = $this->globr($sub_dir, $pattern, $flags);
  135. $files = array_merge($files, $sub_files);
  136. }
  137. return $files;
  138. }
  139. /**
  140. * Allows for PHP functions to be called and be stubbed.
  141. * @warning This function will not work for functions that need
  142. * to pass references; manually define a stub function for those.
  143. */
  144. public function __call($name, $args)
  145. {
  146. return call_user_func_array($name, $args);
  147. }
  148. }
  149. // vim: et sw=4 sts=4