ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjFileAbstractZipProcessor.php
Go to the documentation of this file.
1<?php
2
23
30{
34 private const IRSS_FILEPATH_KEY = 'uri';
35
36 private ?ZipArchive $archive = null;
37 private int $id_type;
38
47
51 public function __construct(
52 ResourceStakeholder $stakeholder,
53 ilObjFileGUI $gui_object,
54 Services $storage,
55 ilFileServicesSettings $settings,
56 private $tree
57 ) {
58 parent::__construct($stakeholder, $gui_object, $storage, $settings);
59
60 $this->id_type = $gui_object->getIdType();
61 }
62
64 {
65 // create one base container with the name of the zip itself, all other containers will be created inside this one
66 $zip_name = $this->storage->manage()->getCurrentRevision($rid)->getInformation()->getTitle();
67 $info = new SplFileInfo($zip_name);
68 $base_path = $info->getBasename("." . $info->getExtension());
69 $base_container = $this->createContainerObj($base_path, $this->gui_object->getParentId());
70
71 return (int) $base_container->getRefId();
72 }
73
77 protected function createContainerObj(string $dir_name, int $parent_id): ilObject
78 {
79 $container_obj = $this->getPossibleContainerObj($parent_id);
80 $container_obj->setTitle($dir_name);
81
82 $container_obj->create();
83 $container_obj->createReference();
84
85 $this->gui_object->putObjectInTree($container_obj, $parent_id);
86
87 return $container_obj;
88 }
89
93 protected function openZip(ResourceIdentification $rid): void
94 {
95 if ($this->archive instanceof \ZipArchive) {
96 throw new LogicException("openZip() can only be called once, yet it was called again.");
97 }
98
99 $file_uri = $this->storage->consume()->stream($rid)->getStream()->getMetadata(self::IRSS_FILEPATH_KEY);
100 $this->archive = new ZipArchive();
101 $this->archive->open($file_uri);
102 }
103
108 private function getZipPaths(): Generator
109 {
110 if (!$this->archive instanceof \ZipArchive) {
111 throw new LogicException("cannot read content of unopened zip archive");
112 }
113
114 for ($i = 0, $i_max = $this->archive->count(); $i < $i_max; $i++) {
115 $path = $this->archive->getNameIndex($i, ZipArchive::FL_UNCHANGED);
116 if (str_contains($path, '__MACOSX')) {
117 continue;
118 }
119 if (str_contains($path, '.DS_')) {
120 continue;
121 }
122
123 yield $path;
124 }
125 }
126
131 protected function getZipFiles(): Generator
132 {
133 foreach ($this->getZipPaths() as $path) {
134 if (str_ends_with($path, "/")) {
135 continue;
136 }
137 if (str_ends_with($path, "\\")) {
138 continue;
139 }
140 yield $path;
141 }
142 }
143
144 protected function hasMultipleRootEntriesInZip(): bool
145 {
146 $amount = 0;
147 foreach ($this->getZipDirectories() as $zip_directory) {
148 $dirname = dirname($zip_directory);
149 if ($dirname === '.') {
150 $amount++;
151 }
152 if ($amount > 1) {
153 return true;
154 }
155 }
156 foreach ($this->getZipFiles() as $zip_file) {
157 $dirname = dirname($zip_file);
158 if ($dirname === '.') {
159 $amount++;
160 }
161 if ($amount > 1) {
162 return true;
163 }
164 }
165 return false;
166 }
167
173 protected function getZipDirectories(): Generator
174 {
175 $directories = [];
176 foreach ($this->getZipPaths() as $path) {
177 if (str_ends_with($path, "/") || str_ends_with($path, "\\")) {
178 $directories[] = $path;
179 continue;
180 }
181 // add all parent directories of files, too. depending on the OS used to create the zip,
182 // these directories may not be present as explicit directory entries in the zip
183 $dir_name = dirname($path) . '/';
184 if ($dir_name !== './' && $dir_name !== '/' && !in_array($dir_name, $directories, true)) {
185 $directories[] = $dir_name;
186 }
187 }
188
189 $directories_with_parents = [];
190
191 foreach ($directories as $directory) {
192 $parent = dirname($directory) . '/';
193 if ($parent !== './' && !in_array($parent, $directories)) {
194 $directories_with_parents[] = $parent;
195 }
196 $directories_with_parents[] = $directory;
197 }
198
199 $directories_with_parents = array_unique($directories_with_parents);
200 sort($directories_with_parents);
201 yield from $directories_with_parents;
202 }
203
207 protected function storeZippedFile(string $file_path): ResourceIdentification
208 {
209 if (!$this->archive instanceof \ZipArchive) {
210 throw new LogicException("No archive has been opened yet, call openZip() first in order to read files.");
211 }
212
213 return $this->storage->manage()->stream(
214 Streams::ofString($this->archive->getFromName($file_path)),
215 $this->stakeholder,
216 basename($file_path)
217 );
218 }
219
223 protected function closeZip(): void
224 {
225 if ($this->archive instanceof \ZipArchive) {
226 $this->archive->close();
227 }
228 }
229
233 protected function isWorkspace(): bool
234 {
235 return (ilObject2GUI::WORKSPACE_NODE_ID === $this->id_type);
236 }
237
241 private function getPossibleContainerObj(int $parent_id): ilObject
242 {
243 $type = ($this->isWorkspace()) ?
244 ilObject::_lookupType($this->tree->lookupObjectId($parent_id)) :
245 ilObject::_lookupType($parent_id, true);
246
247 return match ($type) {
248 'wfld', 'wsrt' => new ilObjWorkspaceFolder(),
249 'cat', 'root' => new ilObjCategory(),
250 default => new ilObjFolder(),
251 };
252 }
253}
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
Class ilObjCategory.
Class ilObjFileAbstractProcessorInterface.
Class ilObjFileAbstractZipProcessor.
createSurroundingContainer(ResourceIdentification $rid)
getZipPaths()
Yields all paths of the currently open zip-archive (without some macos stuff).
closeZip()
Closes the currently open zip-archive.
__construct(ResourceStakeholder $stakeholder, ilObjFileGUI $gui_object, Services $storage, ilFileServicesSettings $settings, private $tree)
getZipDirectories()
Yields the directory-paths of the currently open zip-archive.
bool $create_base_container_for_multiple_root_entries
@description Unzip on operating systems may behave differently when unzipping if there are only one o...
getZipFiles()
Yields the file-paths of the currently open zip-archive.
createContainerObj(string $dir_name, int $parent_id)
Creates a container object depending on the parent's node type and returns it.
storeZippedFile(string $file_path)
Creates an IRSS resource from the given filepath.
openZip(ResourceIdentification $rid)
Opens the zip archive of the given resource.
getPossibleContainerObj(int $parent_id)
Returns a container object that is possible for the given parent.
isWorkspace()
Returns whether the current context is workspace.
GUI class for file objects.
Class ilObjFolder.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilObject Basic functions for all objects.
static _lookupType(int $id, bool $reference=false)
$info
Definition: entry_point.php:21
$path
Definition: ltiservices.php:30
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc