1. <?php
  2. /**
  3. * Backup files for maintenance tasks with fallback logic.
  4. *
  5. * @param string $sourceDir The directory to backup.
  6. * @param string $backupDir The directory to store the backup.
  7. * @param int $numBackups The number of backups to keep.
  8. * @return bool True on success, false on failure.
  9. */
  10. function backupFiles(string $sourceDir, string $backupDir, int $numBackups): bool
  11. {
  12. // Ensure source directory exists
  13. if (!is_dir($sourceDir)) {
  14. error_log("Source directory '$sourceDir' does not exist.");
  15. return false;
  16. }
  17. // Ensure backup directory exists, create if not
  18. if (!is_dir($backupDir)) {
  19. if (!mkdir($backupDir, 0777, true)) {
  20. error_log("Failed to create backup directory '$backupDir'.");
  21. return false;
  22. }
  23. }
  24. $timestamp = date('Y-m-d_H-i-s');
  25. $backupFilename = $backupDir . '/' . $timestamp;
  26. // Copy files to backup directory
  27. if (!copyDir($sourceDir, $backupFilename, true)) { // recursive copy
  28. error_log("Failed to copy files from '$sourceDir' to '$backupFilename'.");
  29. return false;
  30. }
  31. // Cleanup old backups
  32. cleanupOldBackups($backupDir, $numBackups);
  33. return true;
  34. }
  35. /**
  36. * Copies directory recursively.
  37. *
  38. * @param string $source The source directory.
  39. * @param string $destination The destination directory.
  40. * @param bool $recursive Whether to copy recursively.
  41. * @return bool True on success, false on failure.
  42. */
  43. function copyDir(string $source, string $destination, bool $recursive = true): bool {
  44. if (is_dir($source)) {
  45. if (!copyDirRecursive($source, $destination)) {
  46. return false;
  47. }
  48. } else {
  49. copyFile($source, $destination);
  50. }
  51. return true;
  52. }
  53. /**
  54. * Copies directory recursively.
  55. *
  56. * @param string $source The source directory.
  57. * @param string $destination The destination directory.
  58. * @return bool True on success, false on failure.
  59. */
  60. function copyDirRecursive(string $source, string $destination): bool {
  61. $items = scandir($source);
  62. if ($items === false) {
  63. error_log("Failed to read directory '$source'.");
  64. return false;
  65. }
  66. foreach ($items as $item) {
  67. if ($item == '.' || $item == '..') {
  68. continue;
  69. }
  70. $sourcePath = $source . '/' . $item;
  71. $destinationPath = $destination . '/' . $item;
  72. if (is_dir($sourcePath)) {
  73. if (!copyDirRecursive($sourcePath, $destinationPath)) {
  74. return false;
  75. }
  76. } else {
  77. copyFile($sourcePath, $destinationPath);
  78. }
  79. }
  80. return true;
  81. }
  82. /**
  83. * Copies a file.
  84. *
  85. * @param string $source The source file.
  86. * @param string $destination The destination file.
  87. * @return bool True on success, false on failure.
  88. */
  89. function copyFile(string $source, string $destination): bool
  90. {
  91. if (!file_exists($source)) {
  92. error_log("Source file '$source' does not exist.");
  93. return false;
  94. }
  95. if (copy($source, $destination)) {
  96. return true;
  97. } else {
  98. error_log("Failed to copy file from '$source' to '$destination'.");
  99. return false;
  100. }
  101. }
  102. /**
  103. * Cleans up old backups.
  104. *
  105. * @param string $backupDir The backup directory.
  106. * @param int $numBackups The number of backups to keep.
  107. * @return bool True on success, false on failure.
  108. */
  109. function cleanupOldBackups(string $backupDir, int $numBackups): bool
  110. {
  111. $files = glob($backupDir . '/*');
  112. if ($files === false) {
  113. error_log("Failed to list files in '$backupDir'.");
  114. return false;
  115. }
  116. $files = array_reverse($files);
  117. if (count($files) > $numBackups) {

Add your comment