Problem/Motivation
Using Drupal\Core\Archiver\Zip to initialize a zip object from a file path, I'm receiving a ArchiverException Cannot open %file_path, returned error by ZipArchive ZIP_ER_OPEN - 11
I was able to reproduce the issue with:
Ubuntu 14.04
PHP 5.6.23
ZIP lib 1.12.5
Passing a \ZipArchive::CREATE flag to ZipArchive open() method, fixed the problem, but Drupal\Core\Archiver\Zip doesn't allow to pass any additional arguments to constructor.
Proposed resolution
To add a second optional $flags argument in Drupal\Core\Archiver\Zip __constructor() and pass by default \ZipArchive::CREATE (create the archive if not exists) flag.
| Comment | File | Size | Author |
|---|---|---|---|
| #51 | 2850794-51.patch | 9.45 KB | andypost |
| #51 | interdiff.txt | 278 bytes | andypost |
Comments
Comment #2
sdstyles commentedComment #3
Pavan B S commentedRerolled the patch, please review.
Comment #5
JamesK commentedConfirmed that the documentation states the file will be created as needed, which does not happen without this patch. (See https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Archiver%...)
Tested that this patch fixes the issue with:
Before patch, ArchiverException it thrown.
After patch, $zip is set to the Drupal/Core/Archiver/Zip object as expected.
Comment #6
JamesK commentedComment #7
catchThis could use some test coverage.
Comment #8
mr.baileysAdded test coverage.
Comment #11
borisson_This testcoverage looks to be sufficient, that looks really good. It does bring some new coding standards violations though.
Should be removed.
There should be a newline following the method.
There should be a newline at the end of the file.
Comment #12
borisson_Fixed my own nitpicks.
Comment #13
borisson_All I did was fix nitpicks, I feel it's ok for me to set this to RTBC?
Comment #15
borisson_That was the failure in #12 I retested this because that doesn't seem to be related.
Comment #16
borisson_Back to rtbc, because the test is green again.
Comment #17
alexpottLet's use BrowserTestBase here. Using the
file_directory_temp()in a test like this is super risky and has lead to hard to spot random fails in the past. That way we get a real directory. Yes it is a shame we have to install Drupal but the predictability and clean up is important.Comment #18
borisson_Fixed #17.
Comment #20
borisson_That test was green locally, I have no idea why it's not on the testbot.
Comment #22
kevinfunkComment #23
alexpottImo we shouldn't change the default from \ZipArchive::open()... i.e our default should be NULL too. But we should allow passing in flags.
Ah I see. So this change makes us comply with the docs and also probably behave the same as \Drupal\Core\Archiver\Tar
That seems like a good idea.
Comment #25
averagejoe3000Rerolled patch against 9.1.x. The exception message needed to be updated.
Comment #26
RedLucas25 commentedHey, I've been using this patch for a good three years now, it's just that failing test that's blocking this from being committed to master eh?
Comment #27
cilefen commentedAs this is now targeted for Drupal 9, the test will have to use its file management methods.
Comment #29
cilefen commentedHere it is, again as a BrowserTest.
Comment #30
cilefen commentedFix the coding standards.
Comment #32
cilefen commentedThe 8.9.x failures are unrelated.
Comment #33
alexpottLooking back at my comments over 2 years ago - I realise we can use KernelTestBase we just should not use the temporary directory - we can use the sites directory - the test system will clear this up for us.
Can use TestFileCreationTrait (even in a Kernel test) to generate a test file.
Comment #34
rahulrasgon commentedI have updated the patch as per @alexpott comments.
Please review.
Comment #35
alexpottThese are not required for this test.
This is not necessary if you change the test to:
Add extend from
Drupal\KernelTests\Core\File\FileTestBaseinstead of KernelTestBase.We need to file a follow-up issue about
Drupal\KernelTests\Core\File\FileTestBasenot cleaning up after itself.Comment #36
rahulrasgon commented@alexpott, Thank you for reviewing the patch.
I have updated the patch please.
Comment #37
rahulrasgon commentedFixed PHPLint Errors in #36.
Comment #38
idebr commentedAdding a new paramater to the constructor suggests this is something you can overwrite. However, since the plugin manager
\Drupal\Core\Archiver\ArchiverManager::createInstance()only sends the $file_paththis is not something you can change when creating a new plugin instance.I suggest either:
$this->zip->open()https://www.php.net/manual/en/ziparchive.open.php and create a new zip on ZipArchive::ER_NOENT so the code matches what it says on the tin.Comment #39
andypostThere's 2 different bugs
1) no api to create new archive, which could use to add
createlist(array $files)as feature parity to\Archive_Tar, it looks better then exposing default value when extension could be missing2) ability to exclude zip plugin if no zip extension installed in PHP or fallback somehow, better keeps in #3163123: Error: Class 'ZipArchive' not found in Drupal\Core\Archiver\Zip->__construct() (line 30 of core/lib/Drupal/Core/Archiver/Zip.php).
So the issue title could be fixed like "ArchiverZip has no method to create new archive"
Comment #40
andypostThere's different approach, so test could be adopted from #37
Just always pass configuration to plugin
Comment #41
idebr commentedIt seems the test coverage in #37 was lost in #40.
Comment #42
andypost@idebr test from #37 is useless for this change, it needs extra test coverage for both plugins
Comment #43
andypostMy intent is start discussion of plugin config way to solve the issue
The changes in plugins is unnecessary and just shows example of benefits of this approach
Comment #48
collinhaines commentedI've been having to use
touch($file_path);prior to runningnew Zip($file_path);because of not being able to pass flags. PHP 8.0 has deprecated opening an empty zip file:Deprecated function: ZipArchive::open(): Using empty file as ZipArchive is deprecatedContinuing on #40's usage of having configuration via the plugin be each archiver constructor's second parameter, I've adjusted the
$bufferin Tar to default to 512 to match the default value and to prevent afread(): Length parameter must be greater than 0error being thrown.Left the fallback for
$configuration['flags']as 0 in Zip. PHP Documentation has it at zero although my intellisense has it as NULL. ZipArchive's constants appear to start at one so the chances of ZipArchive having a zero constant added in the future seems slim to none.Continuing on #37's test coverage, I've added an overwrite test for the Zip archiver and a basic creation test for the Tar archiver, each extending a new
ArchiverTestBase(that extends the previousFileTestBase). The tests themselves use direct Tar/Zip class constructions; however, the assertions go through the plugin - in an attempt to cover both ends.Comment #49
andypost@collinhaines great job! please fix documentation nitpicks, ++ rtbc
would be great to elaborate available for tar
at least "flags" should be documented
Comment #50
collinhaines commentedAdded in documentation for the
compress,buffer_length, andflagskeys.Comment #51
andypostThank you @collinhaines - fixing cspell
Comment #53
nod_RTBC per #49 doc issues were addressed
Comment #54
alexpottThe current solution looks really nice. Adding more configuration options to the plugins is a great idea. But we need a change record to tell devs about this.
Comment #55
andypostAdded CR https://www.drupal.org/node/3322990
Comment #56
andypostRelated issue #3163123: Error: Class 'ZipArchive' not found in Drupal\Core\Archiver\Zip->__construct() (line 30 of core/lib/Drupal/Core/Archiver/Zip.php). landed but it still a bug
Comment #57
hchonovNow that we have the CR this can go back to RTBC.
Comment #58
alexpottCommitted 70700fc and pushed to 10.1.x. Thanks!