Util.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. declare(strict_types=1);
  3. namespace ZipStream\Test;
  4. use function fgets;
  5. use function pclose;
  6. use function popen;
  7. use function preg_match;
  8. use RecursiveDirectoryIterator;
  9. use RecursiveIteratorIterator;
  10. use function strtolower;
  11. use ZipArchive;
  12. trait Util
  13. {
  14. protected function cmdExists(string $command): bool
  15. {
  16. if (strtolower(\substr(PHP_OS, 0, 3)) === 'win') {
  17. $fp = popen("where $command", 'r');
  18. $result = fgets($fp, 255);
  19. $exists = !preg_match('#Could not find files#', $result);
  20. pclose($fp);
  21. } else { // non-Windows
  22. $fp = popen("which $command", 'r');
  23. $result = fgets($fp, 255);
  24. $exists = !empty($result);
  25. pclose($fp);
  26. }
  27. return $exists;
  28. }
  29. protected function dumpZipContents(string $path): string
  30. {
  31. if (!$this->cmdExists('hexdump')) {
  32. return '';
  33. }
  34. $output = [];
  35. if (!exec("hexdump -C \"$path\" | head -n 50", $output)) {
  36. return '';
  37. }
  38. return "\nHexdump:\n" . implode("\n", $output);
  39. }
  40. protected function validateAndExtractZip(string $zipPath): string
  41. {
  42. $tmpDir = $this->getTmpDir();
  43. $zipArchive = new ZipArchive();
  44. $result = $zipArchive->open($zipPath);
  45. if ($result !== true) {
  46. $codeName = $this->zipArchiveOpenErrorCodeName($result);
  47. $debugInformation = $this->dumpZipContents($zipPath);
  48. $this->fail("Failed to open {$zipPath}. Code: $result ($codeName)$debugInformation");
  49. return $tmpDir;
  50. }
  51. $this->assertSame(0, $zipArchive->status);
  52. $this->assertSame(0, $zipArchive->statusSys);
  53. $zipArchive->extractTo($tmpDir);
  54. $zipArchive->close();
  55. return $tmpDir;
  56. }
  57. protected function zipArchiveOpenErrorCodeName(int $code): string
  58. {
  59. switch ($code) {
  60. case ZipArchive::ER_EXISTS: return 'ER_EXISTS';
  61. case ZipArchive::ER_INCONS: return 'ER_INCONS';
  62. case ZipArchive::ER_INVAL: return 'ER_INVAL';
  63. case ZipArchive::ER_MEMORY: return 'ER_MEMORY';
  64. case ZipArchive::ER_NOENT: return 'ER_NOENT';
  65. case ZipArchive::ER_NOZIP: return 'ER_NOZIP';
  66. case ZipArchive::ER_OPEN: return 'ER_OPEN';
  67. case ZipArchive::ER_READ: return 'ER_READ';
  68. case ZipArchive::ER_SEEK: return 'ER_SEEK';
  69. default: return 'unknown';
  70. }
  71. }
  72. protected function getTmpDir(): string
  73. {
  74. $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest');
  75. unlink($tmp);
  76. mkdir($tmp) or $this->fail('Failed to make directory');
  77. return $tmp;
  78. }
  79. /**
  80. * @return string[]
  81. */
  82. protected function getRecursiveFileList(string $path, bool $includeDirectories = false): array
  83. {
  84. $data = [];
  85. $path = (string) realpath($path);
  86. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
  87. $pathLen = strlen($path);
  88. foreach ($files as $file) {
  89. $filePath = $file->getRealPath();
  90. if (is_dir($filePath) && !$includeDirectories) {
  91. continue;
  92. }
  93. $data[] = substr($filePath, $pathLen + 1);
  94. }
  95. sort($data);
  96. return $data;
  97. }
  98. }