ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ILIAS\Filesystem\Util\Archive\Unzip Class Reference
+ Collaboration diagram for ILIAS\Filesystem\Util\Archive\Unzip:

Public Member Functions

 __construct (protected UnzipOptions $options, protected FileStream $stream)
 
 getPaths ()
 
 getStreams ()
 
 getFileStreams ()
 
 getAmountOfDirectories ()
 
 getDirectories ()
 Yields the directory-paths of the currently open zip-archive. More...
 
 getAmountOfFiles ()
 
 getFiles ()
 Yields the file-paths of the currently open zip-archive. More...
 
 hasMultipleRootEntriesInZip ()
 
 extract ()
 
 hasZipReadingError ()
 

Data Fields

const DS_UNIX = "/"
 
const DS_WIN = "\\"
 
const BASE_DIR = '.'
 

Protected Member Functions

 pathToStreamGenerator ()
 

Protected Attributes

const URI = 'uri'
 
const DIRECTORY_SEPARATOR = DIRECTORY_SEPARATOR
 
ZipArchive $zip
 
bool $error_reading_zip = false
 
string $path_to_zip
 

Private Attributes

int $amount_of_entries = 0
 

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 Unzip.php.

Constructor & Destructor Documentation

◆ __construct()

ILIAS\Filesystem\Util\Archive\Unzip::__construct ( protected UnzipOptions  $options,
protected FileStream  $stream 
)

Definition at line 44 of file Unzip.php.

47 {
48 $this->path_to_zip = $this->stream->getMetadata(self::URI);
49 $this->zip = new \ZipArchive();
50 try {
51 $this->zip->open($this->path_to_zip, \ZipArchive::RDONLY);
52 $this->amount_of_entries = $this->zip->count();
53 } catch (\Throwable) {
54 $this->error_reading_zip = true;
55 }
56 }

Member Function Documentation

◆ extract()

ILIAS\Filesystem\Util\Archive\Unzip::extract ( )

Definition at line 195 of file Unzip.php.

195 : bool
196 {
197 if ($this->error_reading_zip) {
198 return false;
199 }
200
201 $destination_path = $this->options->getZipOutputPath();
202 if ($destination_path === null) {
203 return false;
204 }
205
206 switch ($this->options->getDirectoryHandling()) {
207 case ZipDirectoryHandling::KEEP_STRUCTURE:
208 break;
209 case ZipDirectoryHandling::ENSURE_SINGLE_TOP_DIR:
210 // top directory with same name as the ZIP without suffix
211 $zip_path = $this->stream->getMetadata(self::URI);
212 $sufix = '.' . pathinfo((string) $zip_path, PATHINFO_EXTENSION);
213 $top_directory = basename((string) $zip_path, $sufix);
214
215 // first we check if the ZIP contains the top directory
216 $has_top_directory = true;
217 foreach ($this->getPaths() as $path) {
218 $has_top_directory = str_starts_with($path, $top_directory) && $has_top_directory;
219 }
220
221 // if not, we prepend the top directory to the destination path
222 if (!$has_top_directory) {
223 $destination_path .= self::DIRECTORY_SEPARATOR . $top_directory;
224 }
225 break;
227 if (!is_dir($destination_path) && (!mkdir($destination_path, 0777, true) && !is_dir($destination_path))) {
228 throw new \RuntimeException(sprintf('Directory "%s" was not created', $destination_path));
229 }
230
231 foreach ($this->getStreams() as $stream) {
232 $uri = $stream->getMetadata(self::URI);
233 if (substr((string) $uri, -1) === self::DIRECTORY_SEPARATOR) {
234 continue; // Skip directories
235 }
236 $file_name = Util::sanitizeFileName($destination_path . self::DIRECTORY_SEPARATOR . basename((string) $uri));
237 file_put_contents(
238 $file_name,
239 $stream->getContents()
240 );
241 }
242 return true; // Stop here
243 }
244
245 $this->zip->extractTo($destination_path, iterator_to_array($this->getPaths()));
246
247 return true;
248 }
static sanitizeFileName(string $filename)
Definition: Util.php:48
$path
Definition: ltiservices.php:30
@ FLAT_STRUCTURE
@description Will keep the top directory of the ZIP file if there is one (simple unzip).

References $path, ILIAS\Filesystem\Util\Archive\FLAT_STRUCTURE, ILIAS\Filesystem\Util\Archive\Unzip\getPaths(), ILIAS\Filesystem\Util\Archive\Unzip\getStreams(), and ILIAS\Filesystem\Util\sanitizeFileName().

+ Here is the call graph for this function:

◆ getAmountOfDirectories()

ILIAS\Filesystem\Util\Archive\Unzip::getAmountOfDirectories ( )

Definition at line 112 of file Unzip.php.

112 : int
113 {
114 return iterator_count($this->getDirectories());
115 }
getDirectories()
Yields the directory-paths of the currently open zip-archive.
Definition: Unzip.php:122

References ILIAS\Filesystem\Util\Archive\Unzip\getDirectories().

+ Here is the call graph for this function:

◆ getAmountOfFiles()

ILIAS\Filesystem\Util\Archive\Unzip::getAmountOfFiles ( )

Definition at line 150 of file Unzip.php.

150 : int
151 {
152 return iterator_count($this->getFiles());
153 }
getFiles()
Yields the file-paths of the currently open zip-archive.
Definition: Unzip.php:159

References ILIAS\Filesystem\Util\Archive\Unzip\getFiles().

+ Here is the call graph for this function:

◆ getDirectories()

ILIAS\Filesystem\Util\Archive\Unzip::getDirectories ( )

Yields the directory-paths of the currently open zip-archive.

This fixes the issue that win and mac zip archives have different directory structures.

Returns
\Generator|string[]

Definition at line 122 of file Unzip.php.

122 : \Generator
123 {
124 $directories = [];
125 foreach ($this->getPaths() as $path) {
126 if (substr($path, -1) === self::DS_UNIX || substr($path, -1) === self::DS_WIN) {
127 $directories[] = $path;
128 continue;
129 }
130 if ((str_contains($path, self::DS_UNIX) || str_contains($path, self::DS_WIN))) {
131 $directories[] = dirname($path) . self::DIRECTORY_SEPARATOR;
132 }
133 }
134
135 $directories_with_parents = [];
136
137 foreach ($directories as $directory) {
138 $parent = dirname($directory) . self::DIRECTORY_SEPARATOR;
139 if ($parent !== self::BASE_DIR . self::DIRECTORY_SEPARATOR && !in_array($parent, $directories, true)) {
140 $directories_with_parents[] = $parent;
141 }
142 $directories_with_parents[] = $directory;
143 }
144
145 $directories_with_parents = array_unique($directories_with_parents);
146 sort($directories_with_parents);
147 yield from $directories_with_parents;
148 }

References $path, ILIAS\Filesystem\Util\Archive\Unzip\DIRECTORY_SEPARATOR, ILIAS\ResourceStorage\Flavour\Machine\DefaultMachines\from(), ILIAS\Filesystem\Util\Archive\Unzip\getPaths(), and ILIAS\UI\examples\Symbol\Glyph\Sort\sort().

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\getAmountOfDirectories(), and ILIAS\Filesystem\Util\Archive\Unzip\hasMultipleRootEntriesInZip().

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

◆ getFiles()

ILIAS\Filesystem\Util\Archive\Unzip::getFiles ( )

Yields the file-paths of the currently open zip-archive.

Returns
\Generator|string[]

Definition at line 159 of file Unzip.php.

159 : \Generator
160 {
161 $files = [];
162 foreach ($this->getPaths() as $path) {
163 if (substr($path, -1) !== self::DS_UNIX && substr($path, -1) !== self::DS_WIN) {
164 $files[] = $path;
165 }
166 }
167 sort($files);
168 yield from $files;
169 }

References $path, ILIAS\ResourceStorage\Flavour\Machine\DefaultMachines\from(), ILIAS\Filesystem\Util\Archive\Unzip\getPaths(), and ILIAS\UI\examples\Symbol\Glyph\Sort\sort().

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\getAmountOfFiles(), ILIAS\Filesystem\Util\Archive\Unzip\getFileStreams(), ILIAS\Filesystem\Util\Archive\Unzip\getStreams(), and ILIAS\Filesystem\Util\Archive\Unzip\hasMultipleRootEntriesInZip().

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

◆ getFileStreams()

ILIAS\Filesystem\Util\Archive\Unzip::getFileStreams ( )
Returns
\Generator|FileStream[]

Definition at line 105 of file Unzip.php.

105 : \Generator
106 {
107 $paths_to_stream_generator = $this->pathToStreamGenerator();
108
109 yield from $paths_to_stream_generator($this->getFiles());
110 }

References ILIAS\ResourceStorage\Flavour\Machine\DefaultMachines\from(), ILIAS\Filesystem\Util\Archive\Unzip\getFiles(), and ILIAS\Filesystem\Util\Archive\Unzip\pathToStreamGenerator().

+ Here is the call graph for this function:

◆ getPaths()

ILIAS\Filesystem\Util\Archive\Unzip::getPaths ( )
Returns
\Generator<bool|string>

Definition at line 75 of file Unzip.php.

75 : \Generator
76 {
77 if (!$this->error_reading_zip) {
78 for ($i = 0, $i_max = $this->amount_of_entries; $i < $i_max; $i++) {
79 $path = $this->zip->getNameIndex($i, \ZipArchive::FL_UNCHANGED);
80 if ($this->isPathIgnored($path, $this->options)) {
81 continue;
82 }
83 yield $path;
84 }
85 }
86 }

References $path.

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\extract(), ILIAS\Filesystem\Util\Archive\Unzip\getDirectories(), ILIAS\Filesystem\Util\Archive\Unzip\getFiles(), and ILIAS\Filesystem\Util\Archive\Unzip\getStreams().

+ Here is the caller graph for this function:

◆ getStreams()

ILIAS\Filesystem\Util\Archive\Unzip::getStreams ( )
Returns
\Generator|FileStream[]

Definition at line 91 of file Unzip.php.

91 : \Generator
92 {
93 $paths_to_stream_generator = $this->pathToStreamGenerator();
94
95 if ($this->options->getDirectoryHandling() === ZipDirectoryHandling::FLAT_STRUCTURE) {
96 yield from $paths_to_stream_generator($this->getFiles());
97 } else {
98 yield from $paths_to_stream_generator($this->getPaths());
99 }
100 }

References ILIAS\Filesystem\Util\Archive\FLAT_STRUCTURE, ILIAS\ResourceStorage\Flavour\Machine\DefaultMachines\from(), ILIAS\Filesystem\Util\Archive\Unzip\getFiles(), ILIAS\Filesystem\Util\Archive\Unzip\getPaths(), and ILIAS\Filesystem\Util\Archive\Unzip\pathToStreamGenerator().

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\extract().

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

◆ hasMultipleRootEntriesInZip()

ILIAS\Filesystem\Util\Archive\Unzip::hasMultipleRootEntriesInZip ( )

Definition at line 171 of file Unzip.php.

171 : bool
172 {
173 $amount = 0;
174 foreach ($this->getDirectories() as $zip_directory) {
175 $dirname = dirname($zip_directory);
176 if ($dirname === self::BASE_DIR) {
177 $amount++;
178 }
179 if ($amount > 1) {
180 return true;
181 }
182 }
183 foreach ($this->getFiles() as $zip_file) {
184 $dirname = dirname($zip_file);
185 if ($dirname === self::BASE_DIR) {
186 $amount++;
187 }
188 if ($amount > 1) {
189 return true;
190 }
191 }
192 return false;
193 }

References ILIAS\Filesystem\Util\Archive\Unzip\getDirectories(), and ILIAS\Filesystem\Util\Archive\Unzip\getFiles().

+ Here is the call graph for this function:

◆ hasZipReadingError()

ILIAS\Filesystem\Util\Archive\Unzip::hasZipReadingError ( )

Definition at line 250 of file Unzip.php.

250 : bool
251 {
253 }

References ILIAS\Filesystem\Util\Archive\Unzip\$error_reading_zip.

◆ pathToStreamGenerator()

ILIAS\Filesystem\Util\Archive\Unzip::pathToStreamGenerator ( )
protected
Returns
\Closure

Definition at line 61 of file Unzip.php.

61 : \Closure
62 {
63 return function (\Generator $paths): \Generator {
64 foreach ($paths as $path) {
65 $resource = $this->zip->getStream($path);
66
67 yield Streams::ofResource($resource);
68 }
69 };
70 }
static ofResource($resource)
Wraps an already created resource with the stream abstraction.
Definition: Streams.php:64

References $path, and ILIAS\Filesystem\Stream\Streams\ofResource().

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\getFileStreams(), and ILIAS\Filesystem\Util\Archive\Unzip\getStreams().

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

Field Documentation

◆ $amount_of_entries

int ILIAS\Filesystem\Util\Archive\Unzip::$amount_of_entries = 0
private

Definition at line 42 of file Unzip.php.

◆ $error_reading_zip

bool ILIAS\Filesystem\Util\Archive\Unzip::$error_reading_zip = false
protected

Definition at line 40 of file Unzip.php.

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\hasZipReadingError().

◆ $path_to_zip

string ILIAS\Filesystem\Util\Archive\Unzip::$path_to_zip
protected

Definition at line 41 of file Unzip.php.

◆ $zip

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

Definition at line 39 of file Unzip.php.

◆ BASE_DIR

const ILIAS\Filesystem\Util\Archive\Unzip::BASE_DIR = '.'

Definition at line 38 of file Unzip.php.

◆ DIRECTORY_SEPARATOR

const ILIAS\Filesystem\Util\Archive\Unzip::DIRECTORY_SEPARATOR = DIRECTORY_SEPARATOR
protected

Definition at line 35 of file Unzip.php.

Referenced by ILIAS\Filesystem\Util\Archive\Unzip\getDirectories().

◆ DS_UNIX

const ILIAS\Filesystem\Util\Archive\Unzip::DS_UNIX = "/"

Definition at line 36 of file Unzip.php.

◆ DS_WIN

const ILIAS\Filesystem\Util\Archive\Unzip::DS_WIN = "\\"

Definition at line 37 of file Unzip.php.

◆ URI

const ILIAS\Filesystem\Util\Archive\Unzip::URI = 'uri'
protected

Definition at line 34 of file Unzip.php.


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