Download the PHP package wp-php-toolkit/zip without Composer
On this page you can find all versions of the php package wp-php-toolkit/zip. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download wp-php-toolkit/zip
More information about wp-php-toolkit/zip
Files in wp-php-toolkit/zip
Package zip
Short Description Zip component for WordPress.
License GPL-2.0-or-later
Homepage https://wordpress.github.io/php-toolkit/reference/zip.html
Informations about the package zip
slug: zip title: Zip install: wp-php-toolkit/zip
see_also:
- ../learn/02-streaming-archives.html | Tutorial — Streaming archives | Walk through ZIP and EPUB writers from the toolkit's worked example.
- filesystem | Filesystem | Treat an archive like a swappable filesystem backend.
- bytestream | ByteStream | Feed readers and writers without whole-file buffers.
-
httpclient | HttpClient | Stream downloaded archives into validation or extraction workflows.
Read and write ZIP archives without libzip or ZipArchive. Stored entries are pure PHP; Deflate entries use PHP's zlib functions. Entries stream one at a time, while ZIP metadata such as the central directory is still held in memory.
Why this exists
Common PHP ZIP workflows rely on the ZipArchive extension or shelling out to zip. Those are awkward in hosts without libzip, WebAssembly builds, and code paths that need to stream archive data through toolkit byte streams.
The Zip component reads and writes Stored and Deflate archives without ZipArchive. The decoder is pull-based for entry bodies, but ZipFilesystem indexes the central directory in memory and currently rejects archives whose central directory exceeds 2 MB. The encoder accepts any ByteWriteStream as a sink and writes one entry at a time.
Read a file out of a ZIP
ZipFilesystem implements this toolkit's Filesystem interface, so once you wrap the byte reader you can call get_contents(), ls(), and is_dir() just like the other read backends.
Try this: after Run, add a second append_file() call before $enc->close() for a notes.md entry, then call print_r( $zip->ls( '/' ) ) at the end. The directory listing reflects the new entry without re-reading the file.
Build an EPUB from scratch
An EPUB follows one strict ZIP rule: write the mimetype entry first and store it without compression. Deflate the rest of the archive normally.
Gotcha: E-readers reject EPUBs whose mimetype entry has compression. Use COMPRESSION_NONE for that single entry.
Stream a large entry without buffering it
Calling get_contents() on a 500 MB CSV inside a ZIP would eat 500 MB of RAM. Use open_read_stream() instead and inflate-as-you-go.
Gotcha: Only one entry stream open at a time. Drain or finish the previous stream before opening the next.
Repack: modify one file, copy the rest
Updating one file in a ZIP without rewriting the others is impossible at the format level — the central directory points at byte offsets. The pragmatic answer is repack: stream the source archive into a new one, swapping the file you care about.
Defend against zip-slip
A malicious archive can name an entry ../../etc/passwd and trick a naive extractor into clobbering files outside the destination. ZipDecoder::sanitize_path() normalizes slashes and strips leading traversal segments before exposing the path. Treat it as one layer of defense; still extract through a chrooted filesystem target.
Pipe ZIP entries into an InMemoryFilesystem
Real-world recipe: take an uploaded plugin ZIP, expand it into an InMemoryFilesystem so you can validate, edit, or scan it before it ever touches disk. Three components compose into something you couldn't build with ZipArchive alone.
When to use which type
| Use | For |
|---|---|
ZipFilesystem::create() | Reading. You want get_contents(), ls(), is_dir() over a ZIP. The most common case. |
ZipEncoder | Writing. Stream entries into any ByteWriteStream sink. Required when format rules matter (EPUB, .docx). |
ZipDecoder | Low-level read access to the central directory and individual entry headers. Most code reaches for ZipFilesystem instead. |
open_read_stream() on a ZipFilesystem | Inflating a single large entry without buffering it whole in memory. |
copy_between_filesystems() | Moving entries from a ZIP into another filesystem (memory, local, SQLite). |
Footgun: Updating an entry in place is impossible. The central directory points at byte offsets — change one entry's compressed size and every later offset shifts. Repack into a new archive instead.
Footgun: Never extract entry paths verbatim. Always run paths through ZipDecoder::sanitize_path() and write through a filesystem layer that prevents path escape. Without those checks, a hostile archive can write outside the destination directory.
Footgun: Encrypted archives aren't supported. If you need to read AES-encrypted ZIPs, this isn't the component. The file format technically allows encryption, but the toolkit deliberately excludes it because the implementation surface is large and the use case is rare in WordPress contexts.
Footgun: ZIP64 and very large central directories aren't supported by ZipFilesystem. Entry bodies can stream, but the archive index is bounded by MAX_CENTRAL_DIRECTORY_SIZE.
All versions of zip with dependencies
wp-php-toolkit/bytestream Version ^0.8.1
wp-php-toolkit/filesystem Version ^0.8.1
wp-php-toolkit/http-client Version ^0.8.1