ILIAS  trunk Revision v12.0_alpha-1221-g4e438232683
ILIAS\Filesystem\Util\Archive\Zip Class Reference
+ Collaboration diagram for ILIAS\Filesystem\Util\Archive\Zip:

Public Member Functions

 __construct (protected ZipOptions $options, FileStream ... $streams)
 
 get ()
 
 destroy ()
 @description Explicitly close the zip file and remove the file from the filesystem. More...
 
 addPath (string $path, ?string $path_inside_zip=null)
 
 addStream (FileStream $stream, string $path_inside_zip)
 

Data Fields

const DOT_EMPTY = '.empty'
 
const ITERATION_FACTOR = 0.9
 

Protected Attributes

ZipArchive $zip
 

Private Member Functions

 maybeOpenZip (int $flags=0)
 
 buildTempPath ()
 
 registerShutdownFunction (\Closure $c)
 
 storeZIPtoFilesystem ()
 

Private Attributes

string $zip_output_file = ''
 
int $iteration_limit
 
int $store_counter = 1
 
int $path_counter = 1
 
bool $zip_opened = false
 
array $streams = []
 

Detailed Description

Author
Fabian Schmid fabia.nosp@m.n@sr.nosp@m..solu.nosp@m.tion.nosp@m.s

Definition at line 30 of file Zip.php.

Constructor & Destructor Documentation

◆ __construct()

ILIAS\Filesystem\Util\Archive\Zip::__construct ( protected ZipOptions  $options,
FileStream ...  $streams 
)

Definition at line 49 of file Zip.php.

52 {
53 if ($options->getZipOutputPath() !== null && $options->getZipOutputName() !== null) {
54 $this->zip_output_file = $this->ensureDirectorySeperator(
55 $options->getZipOutputPath()
56 ) . $options->getZipOutputName();
57 } else {
58 $this->zip_output_file = $this->buildTempPath();
59 $this->registerShutdownFunction(function (): void {
60 $this->destroy();
61 });
62 }
63 $system_limit = (int) shell_exec('ulimit -n') ?: 0;
64
65 $this->iteration_limit = $system_limit < 10 ? 100 : min(
66 $system_limit / 2,
67 5000
68 );
69
70 $this->zip = new \ZipArchive();
71 if (!file_exists($this->zip_output_file)) {
72 touch($this->zip_output_file);
73 }
74
75 $this->maybeOpenZip(\ZipArchive::OVERWRITE);
76 foreach ($streams as $path_inside_zip => $stream) {
77 $path_inside_zip = is_int($path_inside_zip) ? basename((string) $stream->getMetadata('uri')) : $path_inside_zip;
78 $this->addStream($stream, basename($path_inside_zip));
79 }
80 }
destroy()
@description Explicitly close the zip file and remove the file from the filesystem.
Definition: Zip.php:165
maybeOpenZip(int $flags=0)
Definition: Zip.php:82
registerShutdownFunction(\Closure $c)
Definition: Zip.php:110
addStream(FileStream $stream, string $path_inside_zip)
Definition: Zip.php:193

References ILIAS\UI\Implementation\Component\Input\Field\$options, ILIAS\Filesystem\Util\Archive\Zip\$streams, ILIAS\Filesystem\Util\Archive\Zip\addStream(), ILIAS\Filesystem\Util\Archive\Zip\buildTempPath(), ILIAS\Filesystem\Util\Archive\Zip\destroy(), ILIAS\Repository\int(), ILIAS\Filesystem\Util\Archive\Zip\maybeOpenZip(), and ILIAS\Filesystem\Util\Archive\Zip\registerShutdownFunction().

+ Here is the call graph for this function:

Member Function Documentation

◆ addPath()

ILIAS\Filesystem\Util\Archive\Zip::addPath ( string  $path,
?string  $path_inside_zip = null 
)
Deprecated:
in general, it should be avoided to operate with correct paths in the file system. it is also usually not necessary to zip whole directories, as a ZIP can be seen as an "on-the-fly" compilation of different streams. However, since ILIAS still relies on zipping entire directories in many places, this method is still offered for the moment.

Definition at line 178 of file Zip.php.

178 : void
179 {
180 $path_inside_zip ??= basename($path);
181
182 $this->maybeOpenZip();
183
184 // create directory if it does not exist
185 $this->zip->addEmptyDir(rtrim(dirname($path_inside_zip), '/') . '/');
186
187 $this->addStream(
188 Streams::ofResource(fopen($path, 'rb')),
189 $path_inside_zip
190 );
191 }
static ofResource($resource)
Wraps an already created resource with the stream abstraction.
Definition: Streams.php:64
$path
Definition: ltiservices.php:30

References $path, ILIAS\Filesystem\Util\Archive\Zip\addStream(), ILIAS\Filesystem\Util\Archive\Zip\maybeOpenZip(), and ILIAS\Filesystem\Stream\Streams\ofResource().

+ Here is the call graph for this function:

◆ addStream()

ILIAS\Filesystem\Util\Archive\Zip::addStream ( FileStream  $stream,
string  $path_inside_zip 
)

Definition at line 193 of file Zip.php.

193 : void
194 {
195 // we remove the "empty zip file" now if possible
196 if (isset($this->streams[self::DOT_EMPTY])) {
197 unset($this->streams[self::DOT_EMPTY]);
198 }
199
200 // we must store the ZIP to e temporary files every 1000 files, otherwise we will get a Too Many Open Files error
201 $this->streams[$path_inside_zip] = $stream;
202
203 if (
204 $this->path_counter === $this->iteration_limit
205 || count(get_resources('stream')) > ($this->iteration_limit * self::ITERATION_FACTOR)
206 ) {
207 $this->storeZIPtoFilesystem();
208 $this->streams = [];
209 $this->path_counter = 0;
210 } else {
211 $this->path_counter++;
212 }
213 }

References ILIAS\Filesystem\Util\Archive\Zip\storeZIPtoFilesystem().

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct(), and ILIAS\Filesystem\Util\Archive\Zip\addPath().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildTempPath()

ILIAS\Filesystem\Util\Archive\Zip::buildTempPath ( )
private

Definition at line 96 of file Zip.php.

96 : string
97 {
98 $directory = defined('CLIENT_DATA_DIR') ? \CLIENT_DATA_DIR . '/temp' : sys_get_temp_dir();
99 $tempnam = tempnam($directory, 'zip');
100 if (is_file($tempnam)) {
101 return $tempnam;
102 }
103 if (is_dir($tempnam)) {
104 rmdir($tempnam);
105 touch($tempnam);
106 }
107 return $tempnam;
108 }
const CLIENT_DATA_DIR
Definition: constants.php:46

References CLIENT_DATA_DIR.

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct().

+ Here is the caller graph for this function:

◆ destroy()

ILIAS\Filesystem\Util\Archive\Zip::destroy ( )

@description Explicitly close the zip file and remove the file from the filesystem.

In general, temp files are deleted whyle destroying the object. but in cases like migrations, you should call this method explicitly. Please note that also explicitly set paths (non-temp) are deleted if you call this method.

Definition at line 165 of file Zip.php.

165 : void
166 {
167 if (file_exists($this->zip_output_file)) {
168 unlink($this->zip_output_file);
169 }
170 }

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct().

+ Here is the caller graph for this function:

◆ get()

ILIAS\Filesystem\Util\Archive\Zip::get ( )

Definition at line 149 of file Zip.php.

149 : Stream
150 {
151 $this->maybeOpenZip();
152 $this->storeZIPtoFilesystem();
153
154 $this->zip->close();
155 $this->zip_opened = false;
156
157 return Streams::ofResource(fopen($this->zip_output_file, 'rb'));
158 }

References ILIAS\Filesystem\Util\Archive\Zip\maybeOpenZip(), ILIAS\Filesystem\Stream\Streams\ofResource(), and ILIAS\Filesystem\Util\Archive\Zip\storeZIPtoFilesystem().

+ Here is the call graph for this function:

◆ maybeOpenZip()

ILIAS\Filesystem\Util\Archive\Zip::maybeOpenZip ( int  $flags = 0)
private

Definition at line 82 of file Zip.php.

82 : void
83 {
84 if (!$this->zip_opened) {
85 if ($flags === 0) {
86 $this->zip_opened = $this->zip->open($this->zip_output_file) === true;
87 } else {
88 $this->zip_opened = $this->zip->open($this->zip_output_file, $flags) === true;
89 }
90 }
91 if (!$this->zip_opened) {
92 throw new \Exception("cannot open <$this->zip_output_file>\n");
93 }
94 }

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct(), ILIAS\Filesystem\Util\Archive\Zip\addPath(), ILIAS\Filesystem\Util\Archive\Zip\get(), and ILIAS\Filesystem\Util\Archive\Zip\storeZIPtoFilesystem().

+ Here is the caller graph for this function:

◆ registerShutdownFunction()

ILIAS\Filesystem\Util\Archive\Zip::registerShutdownFunction ( \Closure  $c)
private

Definition at line 110 of file Zip.php.

110 : void
111 {
112 register_shutdown_function($c);
113 }
$c
Definition: deliver.php:25

References $c.

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct().

+ Here is the caller graph for this function:

◆ storeZIPtoFilesystem()

ILIAS\Filesystem\Util\Archive\Zip::storeZIPtoFilesystem ( )
private

Definition at line 115 of file Zip.php.

115 : void
116 {
117 foreach ($this->streams as $path_inside_zip => $stream) {
118 $path = $stream->getMetadata('uri');
119 if ($this->store_counter === 0) {
120 $this->maybeOpenZip();
121 }
122 if (is_int($path_inside_zip)) {
123 $path_inside_zip = basename((string) $path);
124 }
125
126 if ($path === 'php://memory') {
127 $this->zip->addFromString($path_inside_zip, (string) $stream);
128 $stream->close();
129 } elseif (is_file($path)) {
130 $this->zip->addFile($path, $path_inside_zip);
131 $stream->close();
132 } else {
133 continue;
134 }
135
136 if (
137 $this->store_counter === $this->iteration_limit
138 || count(get_resources('stream')) > ($this->iteration_limit * self::ITERATION_FACTOR)
139 ) {
140 $this->zip->close();
141 $this->zip_opened = false;
142 $this->store_counter = 0;
143 } else {
144 $this->store_counter++;
145 }
146 }
147 }

References $path, and ILIAS\Filesystem\Util\Archive\Zip\maybeOpenZip().

Referenced by ILIAS\Filesystem\Util\Archive\Zip\addStream(), and ILIAS\Filesystem\Util\Archive\Zip\get().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $iteration_limit

int ILIAS\Filesystem\Util\Archive\Zip::$iteration_limit
private

Definition at line 38 of file Zip.php.

◆ $path_counter

int ILIAS\Filesystem\Util\Archive\Zip::$path_counter = 1
private

Definition at line 40 of file Zip.php.

◆ $store_counter

int ILIAS\Filesystem\Util\Archive\Zip::$store_counter = 1
private

Definition at line 39 of file Zip.php.

◆ $streams

array ILIAS\Filesystem\Util\Archive\Zip::$streams = []
private

Definition at line 47 of file Zip.php.

Referenced by ILIAS\Filesystem\Util\Archive\Zip\__construct().

◆ $zip

ZipArchive ILIAS\Filesystem\Util\Archive\Zip::$zip
protected

Definition at line 37 of file Zip.php.

◆ $zip_opened

bool ILIAS\Filesystem\Util\Archive\Zip::$zip_opened = false
private

Definition at line 42 of file Zip.php.

◆ $zip_output_file

string ILIAS\Filesystem\Util\Archive\Zip::$zip_output_file = ''
private

Definition at line 36 of file Zip.php.

◆ DOT_EMPTY

const ILIAS\Filesystem\Util\Archive\Zip::DOT_EMPTY = '.empty'

Definition at line 34 of file Zip.php.

Referenced by ILIAS\Filesystem\Util\Archive\Archives\zip().

◆ ITERATION_FACTOR

const ILIAS\Filesystem\Util\Archive\Zip::ITERATION_FACTOR = 0.9

Definition at line 35 of file Zip.php.


The documentation for this class was generated from the following file: