ZipArchiver.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * @package Grav\Common\Filesystem
  4. *
  5. * @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common\Filesystem;
  9. use InvalidArgumentException;
  10. use RuntimeException;
  11. use ZipArchive;
  12. use function extension_loaded;
  13. use function strlen;
  14. /**
  15. * Class ZipArchiver
  16. * @package Grav\Common\Filesystem
  17. */
  18. class ZipArchiver extends Archiver
  19. {
  20. /**
  21. * @param string $destination
  22. * @param callable|null $status
  23. * @return $this
  24. */
  25. public function extract($destination, callable $status = null)
  26. {
  27. $zip = new ZipArchive();
  28. $archive = $zip->open($this->archive_file);
  29. if ($archive === true) {
  30. Folder::create($destination);
  31. if (!$zip->extractTo($destination)) {
  32. throw new RuntimeException('ZipArchiver: ZIP failed to extract ' . $this->archive_file . ' to ' . $destination);
  33. }
  34. $zip->close();
  35. return $this;
  36. }
  37. throw new RuntimeException('ZipArchiver: Failed to open ' . $this->archive_file);
  38. }
  39. /**
  40. * @param string $source
  41. * @param callable|null $status
  42. * @return $this
  43. */
  44. public function compress($source, callable $status = null)
  45. {
  46. if (!extension_loaded('zip')) {
  47. throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
  48. }
  49. // Get real path for our folder
  50. $rootPath = realpath($source);
  51. if (!$rootPath) {
  52. throw new InvalidArgumentException('ZipArchiver: ' . $source . ' cannot be found...');
  53. }
  54. $zip = new ZipArchive();
  55. if (!$zip->open($this->archive_file, ZipArchive::CREATE)) {
  56. throw new InvalidArgumentException('ZipArchiver:' . $this->archive_file . ' cannot be created...');
  57. }
  58. $files = $this->getArchiveFiles($rootPath);
  59. $status && $status([
  60. 'type' => 'count',
  61. 'steps' => iterator_count($files),
  62. ]);
  63. foreach ($files as $file) {
  64. $filePath = $file->getPathname();
  65. $relativePath = ltrim(substr($filePath, strlen($rootPath)), '/');
  66. if ($file->isDir()) {
  67. $zip->addEmptyDir($relativePath);
  68. } else {
  69. $zip->addFile($filePath, $relativePath);
  70. }
  71. $status && $status([
  72. 'type' => 'progress',
  73. ]);
  74. }
  75. $status && $status([
  76. 'type' => 'message',
  77. 'message' => 'Compressing...'
  78. ]);
  79. $zip->close();
  80. return $this;
  81. }
  82. /**
  83. * @param array $folders
  84. * @param callable|null $status
  85. * @return $this
  86. */
  87. public function addEmptyFolders($folders, callable $status = null)
  88. {
  89. if (!extension_loaded('zip')) {
  90. throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
  91. }
  92. $zip = new ZipArchive();
  93. if (!$zip->open($this->archive_file)) {
  94. throw new InvalidArgumentException('ZipArchiver: ' . $this->archive_file . ' cannot be opened...');
  95. }
  96. $status && $status([
  97. 'type' => 'message',
  98. 'message' => 'Adding empty folders...'
  99. ]);
  100. foreach ($folders as $folder) {
  101. $zip->addEmptyDir($folder);
  102. $status && $status([
  103. 'type' => 'progress',
  104. ]);
  105. }
  106. $zip->close();
  107. return $this;
  108. }
  109. }