ILIAS  trunk Revision v11.0_alpha-1723-g8e69f309bab
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
ZipTest.php
Go to the documentation of this file.
1 <?php
2 
19 namespace ILIAS\Filesystem\Util;
20 
33 
37 #[BackupGlobals(false)]
38 #[BackupStaticProperties(false)]
39 #[PreserveGlobalState(false)]
40 #[RunTestsInSeparateProcesses]
41 class ZipTest extends TestCase
42 {
43  public const ZIPPED_ZIP = 'zipped.zip';
44  protected string $zips_dir = __DIR__ . '/zips/';
45  protected string $unzips_dir = __DIR__ . '/unzips/';
46 
47  protected function setUp(): void
48  {
49  if (file_exists($this->unzips_dir . self::ZIPPED_ZIP)) {
50  unlink($this->unzips_dir . self::ZIPPED_ZIP);
51  }
52  if (!file_exists($this->unzips_dir)) {
53  mkdir($this->unzips_dir);
54  }
55  }
56 
57  protected function tearDown(): void
58  {
59  if (file_exists($this->unzips_dir)) {
60  $this->recurseRmdir($this->unzips_dir);
61  }
62  }
63 
64  public function testZip(): void
65  {
66  $zip_options = new ZipOptions();
67  $streams = [
68  Streams::ofResource(fopen($this->zips_dir . '1_folder_1_file_mac.zip', 'r')),
69  Streams::ofResource(fopen($this->zips_dir . '1_folder_win.zip', 'r')),
70  ];
71  $zip = new Zip($zip_options, ...$streams);
72  $zip_stream = $zip->get();
73  $this->assertGreaterThan(0, $zip_stream->getSize());
74 
75  $unzip_again = new Unzip(new UnzipOptions(), $zip_stream);
76  $this->assertEquals(2, $unzip_again->getAmountOfFiles());
77  }
78 
79  public function testLegacyZip(): void
80  {
81  $legacy = new LegacyArchives();
82 
83  define('CLIENT_WEB_DIR', __DIR__);
84  define('ILIAS_WEB_DIR', 'public/data');
85  define('CLIENT_ID', 'test');
86  define('CLIENT_DATA_DIR', __DIR__);
87  define('ILIAS_ABSOLUTE_PATH', __DIR__);
88 
89  $legacy->zip($this->zips_dir, $this->unzips_dir . self::ZIPPED_ZIP, false);
90  $this->assertFileExists($this->unzips_dir . self::ZIPPED_ZIP);
91 
92  $unzip_again = new Unzip(new UnzipOptions(), Streams::ofResource(fopen($this->unzips_dir . self::ZIPPED_ZIP, 'r')));
93  $this->assertEquals(5, $unzip_again->getAmountOfFiles());
94 
95  $depth = 0;
96  foreach ($unzip_again->getPaths() as $path) {
97  $parts = explode('/', $path);
98  $depth = max($depth, count($parts));
99  }
100  $this->assertEquals(2, $depth);
101  $this->recurseRmdir($this->unzips_dir);
102  }
103 
104  public function LegacyZipWithTop(): void
105  {
106  $legacy = new LegacyArchives();
107 
108  define('CLIENT_WEB_DIR', __DIR__);
109  define('ILIAS_WEB_DIR', 'public/data');
110  define('CLIENT_ID', 'test');
111  define('CLIENT_DATA_DIR', __DIR__);
112  define('ILIAS_ABSOLUTE_PATH', __DIR__);
113 
114  mkdir($this->unzips_dir);
115  $legacy->zip($this->zips_dir, $this->unzips_dir . self::ZIPPED_ZIP, true);
116  $this->assertFileExists($this->unzips_dir . self::ZIPPED_ZIP);
117 
118  $unzip_again = new Unzip(new UnzipOptions(), Streams::ofResource(fopen($this->unzips_dir . self::ZIPPED_ZIP, 'r')));
119  $this->assertEquals(5, $unzip_again->getAmountOfFiles());
120 
121  $depth = 0;
122  foreach ($unzip_again->getPaths() as $path) {
123  $parts = explode('/', $path);
124  $depth = max($depth, count($parts));
125  }
126  $this->assertEquals(2, $depth);
127  $this->recurseRmdir($this->unzips_dir);
128  }
129 
134  #[DataProvider('getZips')]
135  public function testUnzip(
136  string $zip,
137  bool $has_multiple_root_entries,
138  int $expected_amount_directories,
139  array $expected_directories,
140  int $expected_amount_files,
141  array $expected_files
142  ): void {
143  $this->assertStringContainsString('.zip', $zip);
144  $zip_path = $this->zips_dir . $zip;
145  $this->assertFileExists($zip_path);
146 
147  $stream = Streams::ofResource(fopen($zip_path, 'rb'));
148  $options = new UnzipOptions();
149  $unzip = new Unzip($options, $stream);
150 
151  $this->assertFalse($unzip->hasZipReadingError());
152  $this->assertEquals($has_multiple_root_entries, $unzip->hasMultipleRootEntriesInZip());
153  $this->assertEquals($expected_amount_directories, $unzip->getAmountOfDirectories());
154  $this->assertEquals($expected_directories, iterator_to_array($unzip->getDirectories()));
155  $this->assertEquals($expected_amount_files, $unzip->getAmountOfFiles());
156  $this->assertEquals($expected_files, iterator_to_array($unzip->getFiles()));
157  }
158 
159  public function testWrongZip(): void
160  {
161  $stream = Streams::ofResource(fopen(__FILE__, 'rb'));
162  $options = new UnzipOptions();
163  $unzip = new Unzip($options, $stream);
164  $this->assertTrue($unzip->hasZipReadingError());
165  $this->assertFalse($unzip->hasMultipleRootEntriesInZip());
166  $this->assertEquals(0, iterator_count($unzip->getFiles()));
167  $this->assertEquals(0, iterator_count($unzip->getDirectories()));
168  $this->assertEquals(0, iterator_count($unzip->getPaths()));
169  $this->assertEquals([], iterator_to_array($unzip->getDirectories()));
170  $this->assertEquals([], iterator_to_array($unzip->getFiles()));
171  }
172 
173 
174  public function testLargeZIPs(): void
175  {
176  // get ulimit
177  $ulimit = (int) shell_exec('ulimit -n');
178  $limit = 2500;
179  if ($ulimit >= $limit) {
180  $this->markTestSkipped('ulimit is too high and would take too much resources');
181  }
182  $this->assertLessThan($limit, $ulimit);
183 
184  $zip = new Zip(new ZipOptions());
185 
186  $file_names = [];
187 
188  for ($i = 0; $i < $ulimit * 2; $i++) {
189  $path_inside_zip = $file_names[] = 'test' . $i;
190  $zip->addStream(Streams::ofString('-'), $path_inside_zip);
191  }
192  $this->assertTrue(true); // no warning or error
193 
194  // check if the zip now contains all files
195  $unzip = new Unzip(new UnzipOptions(), $zip->get());
196  $file_names_in_zip = iterator_to_array($unzip->getFiles());
197  sort($file_names);
198  sort($file_names_in_zip);
199  $this->assertEquals($file_names, $file_names_in_zip);
200  }
201 
206  #[DataProvider('getZips')]
207  public function testLegacyUnzip(
208  string $zip,
209  bool $has_multiple_root_entries,
210  int $expected_amount_directories,
211  array $expected_directories,
212  int $expected_amount_files,
213  array $expected_files
214  ): void {
215  $legacy = new LegacyArchives();
216 
217  $this->assertStringContainsString('.zip', $zip);
218  $zip_path = $this->zips_dir . $zip;
219  $this->assertFileExists($zip_path);
220 
221  $temp_unzip_path = $this->unzips_dir . uniqid('unzip', true);
222 
223  $return = $legacy->unzip(
224  $zip_path,
225  $temp_unzip_path
226  );
227 
228  $this->assertTrue($return);
229 
230  $unzipped_files = $this->directoryToArray($temp_unzip_path);
231  $expected_paths = array_merge($expected_directories, $expected_files);
232  sort($expected_paths);
233  $this->assertEquals($expected_paths, $unzipped_files);
234  $this->assertTrue($this->recurseRmdir($temp_unzip_path));
235  }
236 
237  private function recurseRmdir(string $path_to_directory): bool
238  {
239  $files = array_diff(scandir($path_to_directory), ['.', '..']);
240  foreach ($files as $file) {
241  (is_dir("$path_to_directory/$file") && !is_link("$path_to_directory/$file")) ? $this->recurseRmdir(
242  "$path_to_directory/$file"
243  ) : unlink("$path_to_directory/$file");
244  }
245  return rmdir($path_to_directory);
246  }
247 
251  private function directoryToArray(string $path_to_directory): array
252  {
253  $iterator = new \RecursiveIteratorIterator(
254  new \RecursiveDirectoryIterator($path_to_directory, \RecursiveDirectoryIterator::SKIP_DOTS),
255  \RecursiveIteratorIterator::SELF_FIRST,
256  \RecursiveIteratorIterator::CATCH_GET_CHILD
257  );
258  $paths = [];
259  foreach ($iterator as $item) {
260  $relative_path = str_replace($path_to_directory . '/', '', $item->getPathname());
261  $paths[] = $item->isDir() ? $relative_path . '/' : $relative_path;
262  }
263 
264  sort($paths);
265 
266  return $paths;
267  }
268 
269  // PROVIDERS
270 
271  public static function getZips(): array
272  {
273  return [
274  ['1_folder_mac.zip', false, 10, self::$directories_one, 15, self::$files_one],
275  ['1_folder_win.zip', false, 10, self::$directories_one, 15, self::$files_one],
276  ['3_folders_mac.zip', true, 9, self::$directories_three, 12, self::$files_three],
277  ['3_folders_win.zip', true, 9, self::$directories_three, 12, self::$files_three],
278  ['1_folder_1_file_mac.zip', true, 3, self::$directories_mixed, 5, self::$files_mixed]
279  ];
280  }
281 
282  protected static array $files_mixed = [
283  0 => '03_Test.pdf',
284  1 => 'Ordner A/01_Test.pdf',
285  2 => 'Ordner A/02_Test.pdf',
286  3 => 'Ordner A/Ordner A_2/07_Test.pdf',
287  4 => 'Ordner A/Ordner A_2/08_Test.pdf'
288  ];
289 
290  protected static array $directories_mixed = [
291  0 => 'Ordner A/',
292  1 => 'Ordner A/Ordner A_1/',
293  2 => 'Ordner A/Ordner A_2/'
294  ];
295 
296  protected static array $directories_one = [
297  0 => 'Ordner 0/',
298  1 => 'Ordner 0/Ordner A/',
299  2 => 'Ordner 0/Ordner A/Ordner A_1/',
300  3 => 'Ordner 0/Ordner A/Ordner A_2/',
301  4 => 'Ordner 0/Ordner B/',
302  5 => 'Ordner 0/Ordner B/Ordner B_1/',
303  6 => 'Ordner 0/Ordner B/Ordner B_2/',
304  7 => 'Ordner 0/Ordner C/',
305  8 => 'Ordner 0/Ordner C/Ordner C_1/',
306  9 => 'Ordner 0/Ordner C/Ordner C_2/'
307  ];
308  protected static array $directories_three = [
309  0 => 'Ordner A/',
310  1 => 'Ordner A/Ordner A_1/',
311  2 => 'Ordner A/Ordner A_2/',
312  3 => 'Ordner B/',
313  4 => 'Ordner B/Ordner B_1/',
314  5 => 'Ordner B/Ordner B_2/',
315  6 => 'Ordner C/',
316  7 => 'Ordner C/Ordner C_1/',
317  8 => 'Ordner C/Ordner C_2/'
318  ];
319 
320  protected static array $files_one = [
321  0 => 'Ordner 0/13_Test.pdf',
322  1 => 'Ordner 0/14_Test.pdf',
323  2 => 'Ordner 0/15_Test.pdf',
324  3 => 'Ordner 0/Ordner A/01_Test.pdf',
325  4 => 'Ordner 0/Ordner A/02_Test.pdf',
326  5 => 'Ordner 0/Ordner A/Ordner A_2/07_Test.pdf',
327  6 => 'Ordner 0/Ordner A/Ordner A_2/08_Test.pdf',
328  7 => 'Ordner 0/Ordner B/03_Test.pdf',
329  8 => 'Ordner 0/Ordner B/04_Test.pdf',
330  9 => 'Ordner 0/Ordner B/Ordner B_2/09_Test.pdf',
331  10 => 'Ordner 0/Ordner B/Ordner B_2/10_Test.pdf',
332  11 => 'Ordner 0/Ordner C/05_Test.pdf',
333  12 => 'Ordner 0/Ordner C/06_Test.pdf',
334  13 => 'Ordner 0/Ordner C/Ordner C_2/11_Test.pdf',
335  14 => 'Ordner 0/Ordner C/Ordner C_2/12_Test.pdf'
336  ];
337 
338  protected static array $files_three = [
339  0 => 'Ordner A/01_Test.pdf',
340  1 => 'Ordner A/02_Test.pdf',
341  2 => 'Ordner A/Ordner A_2/07_Test.pdf',
342  3 => 'Ordner A/Ordner A_2/08_Test.pdf',
343  4 => 'Ordner B/03_Test.pdf',
344  5 => 'Ordner B/04_Test.pdf',
345  6 => 'Ordner B/Ordner B_2/09_Test.pdf',
346  7 => 'Ordner B/Ordner B_2/10_Test.pdf',
347  8 => 'Ordner C/05_Test.pdf',
348  9 => 'Ordner C/06_Test.pdf',
349  10 => 'Ordner C/Ordner C_2/11_Test.pdf',
350  11 => 'Ordner C/Ordner C_2/12_Test.pdf',
351  ];
352 }
static array static array static array static array $directories_three
Definition: ZipTest.php:308
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
static array static array static array static array static array $files_one
Definition: ZipTest.php:320
directoryToArray(string $path_to_directory)
Definition: ZipTest.php:251
sort()
description: > Example for rendering a Sort Glyph.
Definition: sort.php:41
static array static array static array $directories_one
Definition: ZipTest.php:296
$path
Definition: ltiservices.php:29
testLegacyUnzip(string $zip, bool $has_multiple_root_entries, int $expected_amount_directories, array $expected_directories, int $expected_amount_files, array $expected_files)
Definition: ZipTest.php:207
static array static array $directories_mixed
Definition: ZipTest.php:290
testUnzip(string $zip, bool $has_multiple_root_entries, int $expected_amount_directories, array $expected_directories, int $expected_amount_files, array $expected_files)
Definition: ZipTest.php:135
recurseRmdir(string $path_to_directory)
Definition: ZipTest.php:237
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static array static array static array static array static array static array $files_three
Definition: ZipTest.php:338