ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
ILIAS\FileUpload\FileUploadImpl Class Reference

Class FileUploadImpl. More...

+ Inheritance diagram for ILIAS\FileUpload\FileUploadImpl:
+ Collaboration diagram for ILIAS\FileUpload\FileUploadImpl:

Public Member Functions

 __construct (private PreProcessorManager $processorManager, private Filesystems $filesystems, private GlobalHttpState $globalHttpState, private ?PhpUploadLimit $upload_limit=null)
 FileUploadImpl constructor. More...
 
 moveOneFileTo (UploadResult $uploadResult, string $destination, int $location=Location::STORAGE, string $file_name='', bool $override_existing=false)
 Moves a single File (the attributes, metadata and upload-status of which are contained in UploadResult) to the given destination.The destination is a relative path which refers to the path of the location.
Parameters
UploadResult$uploadResultWhich upload result do you want to move?
string$destinationWhere do you want to move the file?
int$locationLocation::[STORAGE|WEB|CUSTOMIZING]
string$file_nameDo you want to rename the file?
bool$override_existingOverride existing file with same name
More...
 
 moveFilesTo (string $destination, int $location=Location::STORAGE)
 @inheritDoc More...
 
 uploadSizeLimit ()
 @inheritDoc More...
 
 register (PreProcessor $preProcessor)
 @inheritDoc More...
 
 process ()
 @inheritDoc More...
 
 getResults ()
 @inheritDoc More...
 
 hasUploads ()
 @inheritDoc More...
 
 hasBeenProcessed ()
 Return (bool)true if the current upload has already been processed. More...
 
 moveFilesTo (string $destination, int $location=Location::STORAGE)
 Moves all uploaded files to the given destination after the processors had processed the files. More...
 
 moveOneFileTo (UploadResult $uploadResult, string $destination, int $location=Location::STORAGE, string $file_name='', bool $override_existing=false)
 Moves a single File (the attributes, metadata and upload-status of which are contained in UploadResult) to the given destination. More...
 
 uploadSizeLimit ()
 Returns the current upload size limit in bytes. More...
 
 register (PreProcessor $preProcessor)
 Register a new preprocessor instance. More...
 
 process ()
 Invokes all preprocessors for each uploaded file in the sequence they got registered. More...
 
 getResults ()
 Returns the results of the processing and moving operation of the uploaded files. More...
 
 hasUploads ()
 Return (bool)true if one ore more file-uploads are in the current request, (bool)false if not. More...
 
 hasBeenProcessed ()
 Return (bool)true if the current upload has already been processed. More...
 

Private Member Functions

 hardRemoveUpload (string $identifier, ProcessingStatus $status)
 @description This is the very last thing we can do if a preprocessor DENIEs an upload. More...
 
 regenerateUploadResultWithPath (UploadResult $result, string $path)
 Generate an exact copy of the result with the given path. More...
 
 regenerateUploadResultWithCopyError (UploadResult $result, string $errorReason)
 Creates a clone of the given result and set the status to rejected with the passed error message. More...
 
 selectFilesystem (int $location)
 Selects the correct filesystem by the given Location constant. More...
 
 rejectFailedUpload (Metadata $metadata)
 Reject a failed upload with the given metadata. More...
 
 flattenUploadedFiles (array $uploadedFiles)
 

Private Attributes

bool $processed = false
 
bool $moved = false
 
array $uploadResult = []
 
array $rejectedUploadResult = []
 
array $uploadStreams = null
 

Detailed Description

Class FileUploadImpl.

Author
Nicolas Schäfli ns@st.nosp@m.uder.nosp@m.-raim.nosp@m.ann..nosp@m.ch
Since
5.3
Version
1.0.0

Definition at line 47 of file FileUploadImpl.php.

Constructor & Destructor Documentation

◆ __construct()

ILIAS\FileUpload\FileUploadImpl::__construct ( private PreProcessorManager  $processorManager,
private Filesystems  $filesystems,
private GlobalHttpState  $globalHttpState,
private ?PhpUploadLimit  $upload_limit = null 
)

FileUploadImpl constructor.

Parameters
PreProcessorManager$processorManagerThe processor manager which should be used.
Filesystems$filesystemsThe Filesystems implementation which should be used.
GlobalHttpState$globalHttpStateThe http implementation which should be used to detect the uploaded files.

Definition at line 74 of file FileUploadImpl.php.

79 {
80 }

Member Function Documentation

◆ flattenUploadedFiles()

ILIAS\FileUpload\FileUploadImpl::flattenUploadedFiles ( array  $uploadedFiles)
private

Definition at line 354 of file FileUploadImpl.php.

354 : array
355 {
356 $recursiveIterator = new RecursiveIteratorIterator(
357 new RecursiveArrayIterator(
358 $uploadedFiles,
359 RecursiveArrayIterator::CHILD_ARRAYS_ONLY
360 ),
361 RecursiveIteratorIterator::LEAVES_ONLY
362 );
363
364 return iterator_to_array($recursiveIterator, false);
365 }

Referenced by ILIAS\FileUpload\FileUploadImpl\hasUploads(), and ILIAS\FileUpload\FileUploadImpl\process().

+ Here is the caller graph for this function:

◆ getResults()

ILIAS\FileUpload\FileUploadImpl::getResults ( )

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 329 of file FileUploadImpl.php.

329 : array
330 {
331 if ($this->processed) {
332 return array_merge($this->uploadResult, $this->rejectedUploadResult);
333 }
334
335 throw new IllegalStateException('Can not fetch results without processing the uploads.');
336 }

◆ hardRemoveUpload()

ILIAS\FileUpload\FileUploadImpl::hardRemoveUpload ( string  $identifier,
ProcessingStatus  $status 
)
private

@description This is the very last thing we can do if a preprocessor DENIEs an upload.

This is a hard removal, not beautiful, but it works.

Definition at line 86 of file FileUploadImpl.php.

86 : never
87 {
88 // we delete the file from the temporary directory and remove it from the global $_FILES array
89 $file_stream = $this->uploadStreams[$identifier];
90 $uri = $file_stream->getMetadata('uri');
91 $file_stream->close();
92 unlink($uri);
93 unset($this->uploadStreams[$identifier]);
94 unset($_FILES[$identifier]);
95 throw new IllegalStateException($status->getMessage());
96 }

References ILIAS\FileUpload\DTO\ProcessingStatus\getMessage().

Referenced by ILIAS\FileUpload\FileUploadImpl\process().

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

◆ hasBeenProcessed()

ILIAS\FileUpload\FileUploadImpl::hasBeenProcessed ( )

Return (bool)true if the current upload has already been processed.

Since
5.3

Implements ILIAS\FileUpload\FileUpload.

Definition at line 368 of file FileUploadImpl.php.

368 : bool
369 {
370 return $this->processed;
371 }

References ILIAS\FileUpload\FileUploadImpl\$processed.

◆ hasUploads()

ILIAS\FileUpload\FileUploadImpl::hasUploads ( )

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 342 of file FileUploadImpl.php.

342 : bool
343 {
344 if ($this->moved) {
345 return false;
346 }
347
348 $uploadedFiles = $this->flattenUploadedFiles($this->globalHttpState->request()->getUploadedFiles());
349
350 return ($uploadedFiles !== []);
351 }
flattenUploadedFiles(array $uploadedFiles)

References ILIAS\FileUpload\FileUploadImpl\flattenUploadedFiles().

+ Here is the call graph for this function:

◆ moveFilesTo()

ILIAS\FileUpload\FileUploadImpl::moveFilesTo ( string  $destination,
int  $location = Location::STORAGE 
)

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 131 of file FileUploadImpl.php.

131 : void
132 {
133 if (!$this->processed) {
134 throw new \RuntimeException('Can not move unprocessed files.');
135 }
136
137 if ($this->moved) {
138 throw new \RuntimeException('Can not move the files a second time.');
139 }
140
141 $filesystem = $this->selectFilesystem($location);
142 $tempResults = [];
143
144 foreach ($this->uploadResult as $key => $uploadResult) {
145 if ($uploadResult->getStatus()->getCode() === ProcessingStatus::REJECTED) {
146 continue;
147 }
148
149 try {
150 $path = $destination . '/' . $uploadResult->getName();
151 $filesystem->writeStream($path, Streams::ofPsr7Stream($this->uploadStreams[$key]));
152 $tempResults[] = $this->regenerateUploadResultWithPath($uploadResult, $path);
153 } catch (IOException $ex) {
154 $this->regenerateUploadResultWithCopyError($uploadResult, $ex->getMessage());
155 }
156 }
157
158 $this->uploadResult = $tempResults;
159 $this->uploadStreams = null;
160 $this->moved = true;
161 }
$location
Definition: buildRTE.php:22
regenerateUploadResultWithCopyError(UploadResult $result, string $errorReason)
Creates a clone of the given result and set the status to rejected with the passed error message.
selectFilesystem(int $location)
Selects the correct filesystem by the given Location constant.
regenerateUploadResultWithPath(UploadResult $result, string $path)
Generate an exact copy of the result with the given path.
static ofPsr7Stream(StreamInterface $stream)
Create a FileStream from a Psr7 compliant stream.
Definition: Streams.php:121

References $location, ILIAS\FileUpload\FileUploadImpl\$uploadResult, ILIAS\Filesystem\Stream\Streams\ofPsr7Stream(), ILIAS\FileUpload\FileUploadImpl\regenerateUploadResultWithCopyError(), ILIAS\FileUpload\FileUploadImpl\regenerateUploadResultWithPath(), ILIAS\FileUpload\DTO\ProcessingStatus\REJECTED, and ILIAS\FileUpload\FileUploadImpl\selectFilesystem().

+ Here is the call graph for this function:

◆ moveOneFileTo()

ILIAS\FileUpload\FileUploadImpl::moveOneFileTo ( UploadResult  $uploadResult,
string  $destination,
int  $location = Location::STORAGE,
string  $file_name = '',
bool  $override_existing = false 
)

Moves a single File (the attributes, metadata and upload-status of which are contained in UploadResult) to the given destination.The destination is a relative path which refers to the path of the location.

Parameters
UploadResult$uploadResultWhich upload result do you want to move?
string$destinationWhere do you want to move the file?
int$locationLocation::[STORAGE|WEB|CUSTOMIZING]
string$file_nameDo you want to rename the file?
bool$override_existingOverride existing file with same name

Implements ILIAS\FileUpload\FileUpload.

Definition at line 101 of file FileUploadImpl.php.

101 : bool
102 {
103 if (!$this->processed) {
104 throw new \RuntimeException('Can not move unprocessed files.');
105 }
106 $filesystem = $this->selectFilesystem($location);
107 $tempResults = [];
108
109 if ($uploadResult->getStatus()->getCode() === ProcessingStatus::REJECTED) {
110 return false;
111 }
112
113 try {
114 $path = rtrim($destination, "/") . '/' . ($file_name === "" ? $uploadResult->getName() : $file_name);
115 if ($override_existing && $filesystem->has($path)) {
116 $filesystem->delete($path);
117 }
118 $filesystem->writeStream($path, Streams::ofPsr7Stream($this->uploadStreams[$uploadResult->getPath()]));
119 $tempResults[] = $this->regenerateUploadResultWithPath($uploadResult, $path);
120 } catch (IOException $ex) {
121 $this->regenerateUploadResultWithCopyError($uploadResult, $ex->getMessage());
122 }
123
124 return true;
125 }

References $location, ILIAS\FileUpload\FileUploadImpl\$uploadResult, ILIAS\Filesystem\Stream\Streams\ofPsr7Stream(), ILIAS\FileUpload\FileUploadImpl\regenerateUploadResultWithCopyError(), ILIAS\FileUpload\FileUploadImpl\regenerateUploadResultWithPath(), ILIAS\FileUpload\DTO\ProcessingStatus\REJECTED, and ILIAS\FileUpload\FileUploadImpl\selectFilesystem().

+ Here is the call graph for this function:

◆ process()

ILIAS\FileUpload\FileUploadImpl::process ( )

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 252 of file FileUploadImpl.php.

252 : void
253 {
254 if ($this->processed) {
255 throw new IllegalStateException('Can not reprocess the uploaded files.');
256 }
257
258 $uploadedFiles = $this->globalHttpState->request()->getUploadedFiles();
259 $collectFilesFromNestedFields = $this->flattenUploadedFiles($uploadedFiles);
260 foreach ($collectFilesFromNestedFields as $file) {
261 $metadata = new Metadata($file->getClientFilename(), $file->getSize(), $file->getClientMediaType());
262 try {
263 $stream = Streams::ofPsr7Stream($file->getStream());
264 } catch (\RuntimeException) {
265 $this->rejectFailedUpload($metadata);
266 continue;
267 }
268
269 // we take the temporary file name as an identifier as it is the only unique attribute.
270 $identifier = $file->getStream()->getMetadata('uri');
271
272 $identifier = is_array($identifier) ? '' : $identifier;
273
274 $this->uploadStreams[$identifier] = $stream;
275
276 if ($file->getError() === UPLOAD_ERR_OK) {
277 $processingResult = $this->processorManager->process($stream, $metadata);
278
279 // we do discard if the result is a DENIED that there is no further pissibility to process the file.
280 if ($processingResult->getCode() === ProcessingStatus::DENIED) {
281 $this->hardRemoveUpload($identifier, $processingResult);
282 continue;
283 }
284
285 $result = new UploadResult(
286 $metadata->getFilename(),
287 $metadata->getUploadSize(),
288 $metadata->getMimeType(),
289 $metadata->additionalMetaData(),
290 $processingResult,
291 is_string($identifier) ? $identifier : ''
292 );
293 $this->uploadResult[$identifier] = $result;
294 } else {
295 $this->rejectFailedUpload($metadata);
296 }
297 }
298
299 $this->processed = true;
300 }
hardRemoveUpload(string $identifier, ProcessingStatus $status)
@description This is the very last thing we can do if a preprocessor DENIEs an upload.
rejectFailedUpload(Metadata $metadata)
Reject a failed upload with the given metadata.

References ILIAS\FileUpload\DTO\ProcessingStatus\DENIED, ILIAS\FileUpload\FileUploadImpl\flattenUploadedFiles(), ILIAS\FileUpload\FileUploadImpl\hardRemoveUpload(), ILIAS\Filesystem\Stream\Streams\ofPsr7Stream(), and ILIAS\FileUpload\FileUploadImpl\rejectFailedUpload().

+ Here is the call graph for this function:

◆ regenerateUploadResultWithCopyError()

ILIAS\FileUpload\FileUploadImpl::regenerateUploadResultWithCopyError ( UploadResult  $result,
string  $errorReason 
)
private

Creates a clone of the given result and set the status to rejected with the passed error message.

Parameters
UploadResult$resultThe result which should be cloned.
string$errorReasonThe reason why the error occurred.
Returns
UploadResult The newly cloned rejected result.

Definition at line 193 of file FileUploadImpl.php.

194 {
195 return new UploadResult(
196 $result->getName(),
197 $result->getSize(),
198 $result->getMimeType(),
199 $result->getMetaData(),
201 ''
202 );
203 }

References ILIAS\FileUpload\DTO\UploadResult\getMetaData(), ILIAS\FileUpload\DTO\UploadResult\getMimeType(), ILIAS\FileUpload\DTO\UploadResult\getName(), ILIAS\FileUpload\DTO\UploadResult\getSize(), and ILIAS\FileUpload\DTO\ProcessingStatus\REJECTED.

Referenced by ILIAS\FileUpload\FileUploadImpl\moveFilesTo(), and ILIAS\FileUpload\FileUploadImpl\moveOneFileTo().

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

◆ regenerateUploadResultWithPath()

ILIAS\FileUpload\FileUploadImpl::regenerateUploadResultWithPath ( UploadResult  $result,
string  $path 
)
private

Generate an exact copy of the result with the given path.

Parameters
UploadResult$resultThe result which should be cloned.
string$pathThe path which should be set on the result clone.
Returns
UploadResult The cloned result with the given path.

Definition at line 172 of file FileUploadImpl.php.

173 {
174 return new UploadResult(
175 $result->getName(),
176 $result->getSize(),
177 $result->getMimeType(),
178 $result->getMetaData(),
179 $result->getStatus(),
180 $path
181 );
182 }

References ILIAS\FileUpload\DTO\UploadResult\getMetaData(), ILIAS\FileUpload\DTO\UploadResult\getMimeType(), ILIAS\FileUpload\DTO\UploadResult\getName(), ILIAS\FileUpload\DTO\UploadResult\getSize(), and ILIAS\FileUpload\DTO\UploadResult\getStatus().

Referenced by ILIAS\FileUpload\FileUploadImpl\moveFilesTo(), and ILIAS\FileUpload\FileUploadImpl\moveOneFileTo().

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

◆ register()

ILIAS\FileUpload\FileUploadImpl::register ( PreProcessor  $preProcessor)

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 239 of file FileUploadImpl.php.

239 : void
240 {
241 if (!$this->processed) {
242 $this->processorManager->with($preProcessor);
243 } else {
244 throw new IllegalStateException('Can not register processor after the upload was processed.');
245 }
246 }

◆ rejectFailedUpload()

ILIAS\FileUpload\FileUploadImpl::rejectFailedUpload ( Metadata  $metadata)
private

Reject a failed upload with the given metadata.

Parameters
Metadata$metadataThe metadata used to create the rejected result.

Definition at line 308 of file FileUploadImpl.php.

308 : void
309 {
310 //reject failed upload
311 $processingStatus = new ProcessingStatus(ProcessingStatus::REJECTED, 'Upload failed');
312 $extraMetadata = new ImmutableMapWrapper(new EntryLockingStringMap());
313 $result = new UploadResult(
314 $metadata->getFilename(),
315 $metadata->getUploadSize(),
316 $metadata->getMimeType(),
317 $extraMetadata,
318 $processingStatus,
319 ''
320 );
321
322 $this->rejectedUploadResult[] = $result;
323 }
getFilename()
The filename supplied by the browser.
Definition: Metadata.php:76
getMimeType()
Client supplied mime type of the uploaded.
Definition: Metadata.php:118
getUploadSize()
This is always the original file size which was determined by the http service.
Definition: Metadata.php:106

References ILIAS\FileUpload\DTO\Metadata\getFilename(), ILIAS\FileUpload\DTO\Metadata\getMimeType(), ILIAS\FileUpload\DTO\Metadata\getUploadSize(), and ILIAS\FileUpload\DTO\ProcessingStatus\REJECTED.

Referenced by ILIAS\FileUpload\FileUploadImpl\process().

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

◆ selectFilesystem()

ILIAS\FileUpload\FileUploadImpl::selectFilesystem ( int  $location)
private

Selects the correct filesystem by the given Location constant.

Parameters
int$locationThe storage location constant defined within the Location interface.
See also
Location
Exceptions

InvalidArgumentException Thrown if the location is not a valid Location constant.

Definition at line 215 of file FileUploadImpl.php.

215 : Filesystem
216 {
217 return match ($location) {
218 Location::CUSTOMIZING => $this->filesystems->customizing(),
219 Location::STORAGE => $this->filesystems->storage(),
220 Location::WEB => $this->filesystems->web(),
221 Location::TEMPORARY => $this->filesystems->temp(),
222 default => throw new \InvalidArgumentException("No filesystem found for location code \"$location\""),
223 };
224 }
const TEMPORARY
The ILIAS temporary directory.
Definition: Location.php:53
const CUSTOMIZING
The filesystem within the web root where all the skins and plugins are saved.
Definition: Location.php:48
const WEB
The filesystem within the ilias web root.
Definition: Location.php:38
const STORAGE
The filesystem outside of the ilias web root.
Definition: Location.php:43
static filesystems()
Returns the loaded filesystems.

References $location, ILIAS\FileUpload\Location\CUSTOMIZING, ILIAS\Filesystem\filesystems(), ILIAS\FileUpload\Location\STORAGE, ILIAS\FileUpload\Location\TEMPORARY, and ILIAS\FileUpload\Location\WEB.

Referenced by ILIAS\FileUpload\FileUploadImpl\moveFilesTo(), and ILIAS\FileUpload\FileUploadImpl\moveOneFileTo().

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

◆ uploadSizeLimit()

ILIAS\FileUpload\FileUploadImpl::uploadSizeLimit ( )

@inheritDoc

Implements ILIAS\FileUpload\FileUpload.

Definition at line 230 of file FileUploadImpl.php.

230 : int
231 {
232 return $this->upload_limit?->getPhpUploadLimitInBytes() ?? ilFileUtils::getPhpUploadSizeLimitInBytes();
233 }
static getPhpUploadSizeLimitInBytes()

References ilFileUtils\getPhpUploadSizeLimitInBytes().

+ Here is the call graph for this function:

Field Documentation

◆ $moved

bool ILIAS\FileUpload\FileUploadImpl::$moved = false
private

Definition at line 50 of file FileUploadImpl.php.

◆ $processed

bool ILIAS\FileUpload\FileUploadImpl::$processed = false
private

Definition at line 49 of file FileUploadImpl.php.

Referenced by ILIAS\FileUpload\FileUploadImpl\hasBeenProcessed().

◆ $rejectedUploadResult

array ILIAS\FileUpload\FileUploadImpl::$rejectedUploadResult = []
private

Definition at line 58 of file FileUploadImpl.php.

◆ $uploadResult

UploadResult[] ILIAS\FileUpload\FileUploadImpl::$uploadResult = []
private

◆ $uploadStreams

array ILIAS\FileUpload\FileUploadImpl::$uploadStreams = null
private

Definition at line 62 of file FileUploadImpl.php.


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