[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for /lib/filestorage/zip_packer.php and zip_archive.php 19 * 20 * @package core_files 21 * @category phpunit 22 * @copyright 2012 Petr Skoda 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->libdir . '/filestorage/file_progress.php'); 30 31 class core_files_zip_packer_testcase extends advanced_testcase implements file_progress { 32 protected $testfile; 33 protected $files; 34 35 /** 36 * @var array Progress information passed to the progress reporter 37 */ 38 protected $progress; 39 40 protected function setUp() { 41 parent::setUp(); 42 43 $this->testfile = __DIR__.'/fixtures/test.txt'; 44 45 $fs = get_file_storage(); 46 $context = context_system::instance(); 47 if (!$file = $fs->get_file($context->id, 'phpunit', 'data', 0, '/', 'test.txt')) { 48 $file = $fs->create_file_from_pathname( 49 array('contextid'=>$context->id, 'component'=>'phpunit', 'filearea'=>'data', 'itemid'=>0, 'filepath'=>'/', 'filename'=>'test.txt'), 50 $this->testfile); 51 } 52 53 $this->files = array( 54 'test.test' => $this->testfile, 55 'testíček.txt' => $this->testfile, 56 'Prüfung.txt' => $this->testfile, 57 '测试.txt' => $this->testfile, 58 '試験.txt' => $this->testfile, 59 'Žluťoučký/Koníček.txt' => $file, 60 ); 61 } 62 63 public function test_get_packer() { 64 $this->resetAfterTest(false); 65 $packer = get_file_packer(); 66 $this->assertInstanceOf('zip_packer', $packer); 67 68 $packer = get_file_packer('application/zip'); 69 $this->assertInstanceOf('zip_packer', $packer); 70 } 71 72 /** 73 * @depends test_get_packer 74 */ 75 public function test_list_files() { 76 $this->resetAfterTest(false); 77 78 $files = array( 79 __DIR__.'/fixtures/test_moodle_22.zip', 80 __DIR__.'/fixtures/test_moodle.zip', 81 __DIR__.'/fixtures/test_tc_8.zip', 82 __DIR__.'/fixtures/test_7zip_927.zip', 83 __DIR__.'/fixtures/test_winzip_165.zip', 84 __DIR__.'/fixtures/test_winrar_421.zip', 85 __DIR__.'/fixtures/test_thumbsdb.zip', 86 ); 87 88 if (function_exists('normalizer_normalize')) { 89 // Unfortunately there is no way to standardise UTF-8 strings without INTL extension. 90 $files[] = __DIR__.'/fixtures/test_infozip_3.zip'; 91 $files[] = __DIR__.'/fixtures/test_osx_1074.zip'; 92 $files[] = __DIR__.'/fixtures/test_osx_compress.zip'; 93 } 94 95 $packer = get_file_packer('application/zip'); 96 97 foreach ($files as $archive) { 98 $archivefiles = $packer->list_files($archive); 99 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 100 $this->assertTrue(count($this->files) === count($archivefiles) or count($this->files) === count($archivefiles) - 1); // Some zippers create empty dirs. 101 foreach ($archivefiles as $file) { 102 if ($file->pathname === 'Žluťoučký/') { 103 // Some zippers create empty dirs. 104 continue; 105 } 106 $this->assertArrayHasKey($file->pathname, $this->files, "File $file->pathname not extracted properly: ".basename($archive).' '); 107 } 108 } 109 110 // Windows packer supports only DOS encoding. 111 $archive = __DIR__.'/fixtures/test_win8_de.zip'; 112 $archivefiles = $packer->list_files($archive); 113 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 114 $this->assertEquals(2, count($archivefiles)); 115 foreach ($archivefiles as $file) { 116 $this->assertTrue($file->pathname === 'Prüfung.txt' or $file->pathname === 'test.test'); 117 } 118 119 $zip_archive = new zip_archive(); 120 $zip_archive->open(__DIR__.'/fixtures/test_win8_cz.zip', file_archive::OPEN, 'cp852'); 121 $archivefiles = $zip_archive->list_files(); 122 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 123 $this->assertEquals(3, count($archivefiles)); 124 foreach ($archivefiles as $file) { 125 $this->assertTrue($file->pathname === 'Žluťoučký/Koníček.txt' or $file->pathname === 'testíček.txt' or $file->pathname === 'test.test'); 126 } 127 $zip_archive->close(); 128 129 // Empty archive extraction. 130 $archive = __DIR__.'/fixtures/empty.zip'; 131 $archivefiles = $packer->list_files($archive); 132 $this->assertSame(array(), $archivefiles); 133 } 134 135 /** 136 * @depends test_list_files 137 */ 138 public function test_archive_to_pathname() { 139 global $CFG; 140 141 $this->resetAfterTest(false); 142 143 $packer = get_file_packer('application/zip'); 144 $archive = "$CFG->tempdir/archive.zip"; 145 146 $this->assertFileNotExists($archive); 147 $result = $packer->archive_to_pathname($this->files, $archive); 148 $this->assertTrue($result); 149 $this->assertFileExists($archive); 150 151 $archivefiles = $packer->list_files($archive); 152 $this->assertTrue(is_array($archivefiles)); 153 $this->assertEquals(count($this->files), count($archivefiles)); 154 foreach ($archivefiles as $file) { 155 $this->assertArrayHasKey($file->pathname, $this->files); 156 } 157 158 // Test invalid files parameter. 159 $archive = "$CFG->tempdir/archive2.zip"; 160 $this->assertFileNotExists($archive); 161 162 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); 163 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt'); 164 165 $result = $packer->archive_to_pathname($files, $archive, false); 166 $this->assertFalse($result); 167 $this->assertDebuggingCalled(); 168 $this->assertFileNotExists($archive); 169 170 $result = $packer->archive_to_pathname($files, $archive); 171 $this->assertTrue($result); 172 $this->assertFileExists($archive); 173 $this->assertDebuggingCalled(); 174 $archivefiles = $packer->list_files($archive); 175 $this->assertSame(array(), $archivefiles); 176 unlink($archive); 177 178 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); 179 $this->assertFileExists(__DIR__.'/fixtures/test.txt'); 180 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt', 'test.txt'=>__DIR__.'/fixtures/test.txt', 'ytest.txt'=>__DIR__.'/xx/yy/yy.txt'); 181 $result = $packer->archive_to_pathname($files, $archive); 182 $this->assertTrue($result); 183 $this->assertFileExists($archive); 184 $archivefiles = $packer->list_files($archive); 185 $this->assertCount(1, $archivefiles); 186 $this->assertEquals('test.txt', $archivefiles[0]->pathname); 187 $dms = $this->getDebuggingMessages(); 188 $this->assertCount(2, $dms); 189 $this->resetDebugging(); 190 unlink($archive); 191 } 192 193 /** 194 * @depends test_archive_to_pathname 195 */ 196 public function test_archive_to_storage() { 197 $this->resetAfterTest(false); 198 199 $packer = get_file_packer('application/zip'); 200 $fs = get_file_storage(); 201 $context = context_system::instance(); 202 203 $this->assertFalse($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 204 $result = $packer->archive_to_storage($this->files, $context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 205 $this->assertInstanceOf('stored_file', $result); 206 $this->assertTrue($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 207 208 $archivefiles = $result->list_files($packer); 209 $this->assertTrue(is_array($archivefiles)); 210 $this->assertEquals(count($this->files), count($archivefiles)); 211 foreach ($archivefiles as $file) { 212 $this->assertArrayHasKey($file->pathname, $this->files); 213 } 214 } 215 216 /** 217 * @depends test_archive_to_storage 218 */ 219 public function test_extract_to_pathname() { 220 global $CFG; 221 222 $this->resetAfterTest(false); 223 224 $packer = get_file_packer('application/zip'); 225 $fs = get_file_storage(); 226 $context = context_system::instance(); 227 228 $target = "$CFG->tempdir/test/"; 229 $testcontent = file_get_contents($this->testfile); 230 231 @mkdir($target, $CFG->directorypermissions); 232 $this->assertTrue(is_dir($target)); 233 234 $archive = "$CFG->tempdir/archive.zip"; 235 $this->assertFileExists($archive); 236 $result = $packer->extract_to_pathname($archive, $target); 237 $this->assertTrue(is_array($result)); 238 $this->assertEquals(count($this->files), count($result)); 239 foreach ($this->files as $file => $unused) { 240 $this->assertTrue($result[$file]); 241 $this->assertFileExists($target.$file); 242 $this->assertSame($testcontent, file_get_contents($target.$file)); 243 } 244 245 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 246 $this->assertNotEmpty($archive); 247 $result = $packer->extract_to_pathname($archive, $target); 248 $this->assertTrue(is_array($result)); 249 $this->assertEquals(count($this->files), count($result)); 250 foreach ($this->files as $file => $unused) { 251 $this->assertTrue($result[$file]); 252 $this->assertFileExists($target.$file); 253 $this->assertSame($testcontent, file_get_contents($target.$file)); 254 } 255 } 256 257 /** 258 * @depends test_archive_to_storage 259 */ 260 public function test_extract_to_pathname_onlyfiles() { 261 global $CFG; 262 263 $this->resetAfterTest(false); 264 265 $packer = get_file_packer('application/zip'); 266 $fs = get_file_storage(); 267 $context = context_system::instance(); 268 269 $target = "$CFG->tempdir/onlyfiles/"; 270 $testcontent = file_get_contents($this->testfile); 271 272 @mkdir($target, $CFG->directorypermissions); 273 $this->assertTrue(is_dir($target)); 274 275 $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist'); 276 $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles); 277 $donotextract = array_diff(array_keys($this->files), $onlyfiles); 278 279 $archive = "$CFG->tempdir/archive.zip"; 280 $this->assertFileExists($archive); 281 $result = $packer->extract_to_pathname($archive, $target, $onlyfiles); 282 $this->assertTrue(is_array($result)); 283 $this->assertEquals(count($willbeextracted), count($result)); 284 285 foreach ($willbeextracted as $file) { 286 $this->assertTrue($result[$file]); 287 $this->assertFileExists($target.$file); 288 $this->assertSame($testcontent, file_get_contents($target.$file)); 289 } 290 foreach ($donotextract as $file) { 291 $this->assertFalse(isset($result[$file])); 292 $this->assertFileNotExists($target.$file); 293 } 294 295 } 296 297 /** 298 * @depends test_archive_to_storage 299 */ 300 public function test_extract_to_pathname_returnvalue_successful() { 301 global $CFG; 302 303 $this->resetAfterTest(false); 304 305 $packer = get_file_packer('application/zip'); 306 307 $target = make_request_directory(); 308 309 $archive = "$CFG->tempdir/archive.zip"; 310 $this->assertFileExists($archive); 311 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 312 $this->assertTrue($result); 313 } 314 315 /** 316 * @depends test_archive_to_storage 317 */ 318 public function test_extract_to_pathname_returnvalue_failure() { 319 global $CFG; 320 321 $this->resetAfterTest(false); 322 323 $packer = get_file_packer('application/zip'); 324 325 $target = make_request_directory(); 326 327 $archive = "$CFG->tempdir/noarchive.zip"; 328 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 329 $this->assertFalse($result); 330 } 331 332 /** 333 * @depends test_archive_to_storage 334 */ 335 public function test_extract_to_storage() { 336 global $CFG; 337 338 $this->resetAfterTest(false); 339 340 $packer = get_file_packer('application/zip'); 341 $fs = get_file_storage(); 342 $context = context_system::instance(); 343 344 $testcontent = file_get_contents($this->testfile); 345 346 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 347 $this->assertNotEmpty($archive); 348 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 349 $this->assertTrue(is_array($result)); 350 $this->assertEquals(count($this->files), count($result)); 351 foreach ($this->files as $file => $unused) { 352 $this->assertTrue($result[$file]); 353 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 354 $this->assertInstanceOf('stored_file', $stored_file); 355 $this->assertSame($testcontent, $stored_file->get_content()); 356 } 357 358 $archive = "$CFG->tempdir/archive.zip"; 359 $this->assertFileExists($archive); 360 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 361 $this->assertTrue(is_array($result)); 362 $this->assertEquals(count($this->files), count($result)); 363 foreach ($this->files as $file => $unused) { 364 $this->assertTrue($result[$file]); 365 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 366 $this->assertInstanceOf('stored_file', $stored_file); 367 $this->assertSame($testcontent, $stored_file->get_content()); 368 } 369 unlink($archive); 370 } 371 372 /** 373 * @depends test_extract_to_storage 374 */ 375 public function test_add_files() { 376 global $CFG; 377 378 $this->resetAfterTest(false); 379 380 $packer = get_file_packer('application/zip'); 381 $archive = "$CFG->tempdir/archive.zip"; 382 383 $this->assertFileNotExists($archive); 384 $packer->archive_to_pathname(array(), $archive); 385 $this->assertFileExists($archive); 386 387 $zip_archive = new zip_archive(); 388 $zip_archive->open($archive, file_archive::OPEN); 389 $this->assertEquals(0, $zip_archive->count()); 390 391 $zip_archive->add_file_from_string('test.txt', 'test'); 392 $zip_archive->close(); 393 $zip_archive->open($archive, file_archive::OPEN); 394 $this->assertEquals(1, $zip_archive->count()); 395 396 $zip_archive->add_directory('test2'); 397 $zip_archive->close(); 398 $zip_archive->open($archive, file_archive::OPEN); 399 $files = $zip_archive->list_files(); 400 $this->assertCount(2, $files); 401 $this->assertEquals('test.txt', $files[0]->pathname); 402 $this->assertEquals('test2/', $files[1]->pathname); 403 404 $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt'); 405 $this->assertFalse($result); 406 $zip_archive->close(); 407 $zip_archive->open($archive, file_archive::OPEN); 408 $this->assertEquals(2, $zip_archive->count()); 409 $zip_archive->close(); 410 411 unlink($archive); 412 } 413 414 public function test_close_archive() { 415 global $CFG; 416 417 $this->resetAfterTest(true); 418 419 $archive = "$CFG->tempdir/archive.zip"; 420 $textfile = "$CFG->tempdir/textfile.txt"; 421 touch($textfile); 422 423 $this->assertFileNotExists($archive); 424 $this->assertFileExists($textfile); 425 426 // Create archive and close it without files. 427 // (returns true, without any warning). 428 $zip_archive = new zip_archive(); 429 $result = $zip_archive->open($archive, file_archive::CREATE); 430 $this->assertTrue($result); 431 $result = $zip_archive->close(); 432 $this->assertTrue($result); 433 unlink($archive); 434 435 // Create archive and close it with files. 436 // (returns true, without any warning). 437 $zip_archive = new zip_archive(); 438 $result = $zip_archive->open($archive, file_archive::CREATE); 439 $this->assertTrue($result); 440 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 441 $this->assertTrue($result); 442 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 443 $result = $zip_archive->close(); 444 $this->assertTrue($result); 445 unlink($archive); 446 447 // Create archive and close if forcing error. 448 // (returns true for old PHP versions and 449 // false with warnings for new PHP versions). MDL-51863. 450 $zip_archive = new zip_archive(); 451 $result = $zip_archive->open($archive, file_archive::CREATE); 452 $this->assertTrue($result); 453 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 454 $this->assertTrue($result); 455 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 456 $this->assertTrue($result); 457 // Delete the file before closing does force close() to fail. 458 unlink($textfile); 459 // Behavior is different between old PHP versions and new ones. Let's detect it. 460 $result = false; 461 try { 462 // Old PHP versions were not printing any warning. 463 $result = $zip_archive->close(); 464 } catch (Exception $e) { 465 // New PHP versions print PHP Warning. 466 $this->assertInstanceOf('PHPUnit_Framework_Error_Warning', $e); 467 $this->assertContains('ZipArchive::close', $e->getMessage()); 468 } 469 // This is crazy, but it shows how some PHP versions do return true. 470 try { 471 // And some PHP versions do return correctly false (5.4.25, 5.6.14...) 472 $this->assertFalse($result); 473 } catch (Exception $e) { 474 // But others do insist into returning true (5.6.13...). Only can accept them. 475 $this->assertInstanceOf('PHPUnit_Framework_ExpectationFailedException', $e); 476 $this->assertTrue($result); 477 } 478 $this->assertFileNotExists($archive); 479 } 480 481 /** 482 * @depends test_add_files 483 */ 484 public function test_open_archive() { 485 global $CFG; 486 487 $this->resetAfterTest(true); 488 489 $archive = "$CFG->tempdir/archive.zip"; 490 491 $this->assertFileNotExists($archive); 492 493 $zip_archive = new zip_archive(); 494 $result = $zip_archive->open($archive, file_archive::OPEN); 495 $this->assertFalse($result); 496 $this->assertDebuggingCalled(); 497 498 $zip_archive = new zip_archive(); 499 $result = $zip_archive->open($archive, file_archive::CREATE); 500 $this->assertTrue($result); 501 $zip_archive->add_file_from_string('test.txt', 'test'); 502 $zip_archive->close(); 503 $zip_archive->open($archive, file_archive::OPEN); 504 $this->assertEquals(1, $zip_archive->count()); 505 506 $zip_archive = new zip_archive(); 507 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 508 $this->assertTrue($result); 509 $zip_archive->add_file_from_string('test2.txt', 'test'); 510 $zip_archive->close(); 511 $zip_archive->open($archive, file_archive::OPEN); 512 $this->assertEquals(1, $zip_archive->count()); 513 $zip_archive->close(); 514 515 unlink($archive); 516 $zip_archive = new zip_archive(); 517 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 518 $this->assertTrue($result); 519 $zip_archive->add_file_from_string('test2.txt', 'test'); 520 $zip_archive->close(); 521 $zip_archive->open($archive, file_archive::OPEN); 522 $this->assertEquals(1, $zip_archive->count()); 523 $zip_archive->close(); 524 525 unlink($archive); 526 } 527 528 /** 529 * Tests the progress reporting. 530 */ 531 public function test_file_progress() { 532 global $CFG; 533 534 // Set up. 535 $this->resetAfterTest(true); 536 $packer = get_file_packer('application/zip'); 537 $archive = "$CFG->tempdir/archive.zip"; 538 $context = context_system::instance(); 539 540 // Archive to pathname. 541 $this->progress = array(); 542 $result = $packer->archive_to_pathname($this->files, $archive, true, $this); 543 $this->assertTrue($result); 544 // Should send progress at least once per file. 545 $this->assertTrue(count($this->progress) >= count($this->files)); 546 // Each progress will be indeterminate. 547 $this->assertEquals( 548 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 549 $this->progress[0]); 550 551 // Archive to pathname using entire folder and subfolder instead of file list. 552 unlink($archive); 553 $folder = make_temp_directory('zip_packer_progress'); 554 file_put_contents($folder . '/test1.txt', 'hello'); 555 $subfolder = $folder . '/sub'; 556 check_dir_exists($subfolder); 557 file_put_contents($subfolder . '/test2.txt', 'world'); 558 file_put_contents($subfolder . '/test3.txt', 'and'); 559 file_put_contents($subfolder . '/test4.txt', 'other'); 560 file_put_contents($subfolder . '/test5.txt', 'worlds'); 561 $this->progress = array(); 562 $result = $packer->archive_to_pathname(array('' => $folder), $archive, true, $this); 563 $this->assertTrue($result); 564 // Should send progress at least once per file. 565 $this->assertTrue(count($this->progress) >= 5); 566 567 // Archive to storage. 568 $this->progress = array(); 569 $archivefile = $packer->archive_to_storage($this->files, $context->id, 570 'phpunit', 'test', 0, '/', 'archive.zip', null, true, $this); 571 $this->assertInstanceOf('stored_file', $archivefile); 572 $this->assertTrue(count($this->progress) >= count($this->files)); 573 $this->assertEquals( 574 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 575 $this->progress[0]); 576 577 // Extract to pathname. 578 $this->progress = array(); 579 $target = "$CFG->tempdir/test/"; 580 check_dir_exists($target); 581 $result = $packer->extract_to_pathname($archive, $target, null, $this); 582 remove_dir($target); 583 $this->assertEquals(count($this->files), count($result)); 584 $this->assertTrue(count($this->progress) >= count($this->files)); 585 $this->check_progress_toward_max(); 586 587 // Extract to storage (from storage). 588 $this->progress = array(); 589 $result = $packer->extract_to_storage($archivefile, $context->id, 590 'phpunit', 'target', 0, '/', null, $this); 591 $this->assertEquals(count($this->files), count($result)); 592 $this->assertTrue(count($this->progress) >= count($this->files)); 593 $this->check_progress_toward_max(); 594 595 // Extract to storage (from path). 596 $this->progress = array(); 597 $result = $packer->extract_to_storage($archive, $context->id, 598 'phpunit', 'target', 0, '/', null, $this); 599 $this->assertEquals(count($this->files), count($result)); 600 $this->assertTrue(count($this->progress) >= count($this->files)); 601 $this->check_progress_toward_max(); 602 603 // Wipe created disk file. 604 unlink($archive); 605 } 606 607 /** 608 * Checks that progress reported is numeric rather than indeterminate, 609 * and follows the progress reporting rules. 610 */ 611 private function check_progress_toward_max() { 612 $lastvalue = -1; 613 foreach ($this->progress as $progressitem) { 614 list($value, $max) = $progressitem; 615 $this->assertNotEquals(file_progress::INDETERMINATE, $max); 616 $this->assertTrue($value <= $max); 617 $this->assertTrue($value >= $lastvalue); 618 $lastvalue = $value; 619 } 620 } 621 622 /** 623 * Handles file_progress interface. 624 * 625 * @param int $progress 626 * @param int $max 627 */ 628 public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { 629 $this->progress[] = array($progress, $max); 630 } 631 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |