ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilMultipleImagesInputGUI.php
Go to the documentation of this file.
1<?php
2
22
27{
28 public const RENDERING_TEMPLATE = 'tpl.prop_multi_image_inp.html';
29
30 public const ITERATOR_SUBFIELD_NAME = 'iteratorfield';
31 public const STORED_IMAGE_SUBFIELD_NAME = 'storedimage';
32 public const IMAGE_UPLOAD_SUBFIELD_NAME = 'imageupload';
33
34 public const FILE_DATA_INDEX_DODGING_FILE = 'dodging_file';
35
40
44 protected $editElementOrderEnabled = false;
45
46 protected stdClass $dodging_files;
47
51 protected $suffixes = [];
52
53 protected $imageRemovalCommand = 'removeImage';
54
55 protected $imageUploadCommand = 'uploadImage';
56
57 protected ilLanguage $lng;
59 protected GlyphFactory $glyph_factory;
62
69 public function __construct($a_title = "", $a_postvar = "")
70 {
71 parent::__construct($a_title, $a_postvar);
72
73 global $DIC;
74 $this->lng = $DIC->language();
75 $this->tpl = $DIC->ui()->mainTemplate();
76 $this->glyph_factory = $DIC->ui()->factory()->symbol()->glyph();
77 $this->renderer = $DIC->ui()->renderer();
78 $this->upload_limit = $DIC['ui.upload_limit_resolver'];
79
80 $this->setSuffixes(["jpg", "jpeg", "png", "gif"]);
81 $this->setSize(25);
82 $this->validationRegexp = "";
83
85 $manipulator->setPostVar($this->getPostVar());
86 $this->addFormValuesManipulator($manipulator);
87
88 $this->dodging_files = new stdClass();
89
90 $manipulator = new ilMultipleImagesFileSubmissionDataCompletion($this->dodging_files);
91 $this->addFormValuesManipulator($manipulator);
92
94 $manipulator->setPostVar($this->getPostVar());
95 $this->addFormValuesManipulator($manipulator);
96
98 $manipulator->setPostVar($this->getPostVar());
99 $this->addFormValuesManipulator($manipulator);
100 }
101
107 public function setSuffixes($a_suffixes): void
108 {
109 $this->suffixes = $a_suffixes;
110 }
111
117 public function getSuffixes(): array
118 {
119 return $this->suffixes;
120 }
121
125 public function getImageRemovalCommand(): string
126 {
128 }
129
134 {
135 $this->imageRemovalCommand = $imageRemovalCommand;
136 }
137
141 public function getImageUploadCommand(): string
142 {
144 }
145
150 {
151 $this->imageUploadCommand = $imageUploadCommand;
152 }
153
157 public function isEditElementOccuranceEnabled(): bool
158 {
160 }
161
166 {
167 $this->editElementOccuranceEnabled = $editElementOccuranceEnabled;
168 }
169
173 public function isEditElementOrderEnabled(): bool
174 {
176 }
177
182 {
183 $this->editElementOrderEnabled = $editElementOrderEnabled;
184 }
185
190 abstract protected function isValidFilenameInput($filenameInput): bool;
191
197 public function onCheckInput(): bool
198 {
199 $F = $_FILES[$this->getPostVar()];
200
201 $submittedElements = $this->getInput();
202
203 if ($F && ((array) $this->dodging_files) !== []) {
204 $F = array_merge([self::FILE_DATA_INDEX_DODGING_FILE => (array) $this->dodging_files], $F);
205 }
206
207 if ($this->getRequired() && !is_array($F['error'])) {
208 $this->setAlert($this->lng->txt("form_msg_file_no_upload"));
209 return false;
210 } else {
211 foreach ($F['error'] as $index => $error) {
212 // error handling
213 if ($error > 0) {
214 switch ($error) {
215 case UPLOAD_ERR_FORM_SIZE:
216 case UPLOAD_ERR_INI_SIZE:
217 $this->setAlert($this->lng->txt("form_msg_file_size_exceeds"));
218 return false;
219 break;
220
221 case UPLOAD_ERR_PARTIAL:
222 $this->setAlert($this->lng->txt("form_msg_file_partially_uploaded"));
223 return false;
224 break;
225
226 case UPLOAD_ERR_NO_FILE:
227 if (!$this->getRequired()) {
228 break;
229 } elseif (isset($F[self::FILE_DATA_INDEX_DODGING_FILE][$index]) && $F[self::FILE_DATA_INDEX_DODGING_FILE][$index] !== '') {
230 break;
231 }
232 $this->setAlert($this->lng->txt("form_msg_file_no_upload"));
233 return false;
234 break;
235
236 case UPLOAD_ERR_NO_TMP_DIR:
237 $this->setAlert($this->lng->txt("form_msg_file_missing_tmp_dir"));
238 return false;
239 break;
240
241 case UPLOAD_ERR_CANT_WRITE:
242 $this->setAlert($this->lng->txt("form_msg_file_cannot_write_to_disk"));
243 return false;
244 break;
245
246 case UPLOAD_ERR_EXTENSION:
247 $this->setAlert($this->lng->txt("form_msg_file_upload_stopped_ext"));
248 return false;
249 break;
250 }
251 }
252 }
253 }
254
255 if (is_array($F['tmp_name'])) {
256 foreach ($F['tmp_name'] as $index => $tmpname) {
257 $filename = $F['name'][$index];
258 if (is_array($filename)) {
259 $filename = array_shift($filename);
260 $tmpname = array_shift($tmpname);
261 }
262 $filename_arr = pathinfo($filename);
263 $suffix = $filename_arr["extension"] ?? '';
264 $mimetype = $F['type'][$index];
265 $size_bytes = $F['size'][$index];
266 // check suffixes
267 if (strlen($tmpname) && is_array($this->getSuffixes())) {
268 if (!in_array(strtolower($suffix), $this->getSuffixes())) {
269 $this->setAlert($this->lng->txt("form_msg_file_wrong_file_type"));
270 return false;
271 }
272 }
273 }
274 }
275
276 foreach ($F['tmp_name'] as $index => $tmpname) {
277 $filename = $F['name'][$index];
278 if (is_array($filename)) {
279 $filename = array_shift($filename);
280 $tmpname = array_shift($tmpname);
281 }
282 $filename_arr = pathinfo($filename);
283 $suffix = $filename_arr["extension"] ?? '';
284 $mimetype = $F['type'][$index];
285 $size_bytes = $F['size'][$index];
286 // virus handling
287 if (strlen($tmpname)) {
289 if ($vir[0] == false) {
290 $this->setAlert($this->lng->txt("form_msg_file_virus_found") . "<br />" . $vir[1]);
291 return false;
292 }
293 }
294 }
295
296 return $this->checkSubItemsInput();
297 }
298
303 public function render(string $a_mode = ""): string
304 {
306
307 $tpl = $this->getTemplate();
308 $i = 0;
309
311 foreach ($identified_multi_values as $identifier => $value) {
313 $tpl->setCurrentBlock('image');
314
315 $tpl->setVariable('STORED_IMAGE_SRC', $this->fetchContentImageSourceFromValue($value));
316 $tpl->setVariable(
317 'STORED_IMAGE_ALT',
319 );
320 $tpl->setVariable('STORED_IMAGE_FILENAME', $this->fetchContentImageTitleFromValue($value));
321 $tpl->setVariable('STORED_IMAGE_POST_VAR', $this->getMultiValuePostVarSubFieldPosIndexed($identifier, self::STORED_IMAGE_SUBFIELD_NAME, $i));
322
323 $tpl->setVariable('TXT_DELETE_EXISTING', $lng->txt('delete_existing_file'));
324 $tpl->setVariable('IMAGE_CMD_REMOVE', $this->buildMultiValueSubmitVar($identifier, $i, $this->getImageRemovalCommand()));
325
326 $tpl->parseCurrentBlock();
327 }
328
329 $tpl->setCurrentBlock('addimage');
330
331 $tpl->setVariable('IMAGE_BROWSE', $lng->txt('select_file'));
332 $tpl->setVariable('IMAGE_ID', $this->getMultiValuePosIndexedSubFieldId($identifier, self::IMAGE_UPLOAD_SUBFIELD_NAME, $i));
333 $tpl->setVariable('MAX_SIZE_WARNING', $this->lng->txt('form_msg_file_size_exceeds'));
334 $tpl->setVariable('MAX_SIZE', $this->upload_limit->getPhpUploadLimitInBytes());
335 $tpl->setVariable('TXT_IMAGE_SUBMIT', $lng->txt('upload'));
336 $tpl->setVariable('IMAGE_CMD_UPLOAD', $this->buildMultiValueSubmitVar($identifier, $i, $this->getImageUploadCommand()));
337 $tpl->setVariable('UPLOAD_IMAGE_POST_VAR', $this->getMultiValuePostVarSubFieldPosIndexed($identifier, self::IMAGE_UPLOAD_SUBFIELD_NAME, $i));
338 $tpl->setVariable('COUNT_POST_VAR', $this->getMultiValuePostVarSubFieldPosIndexed($identifier, self::ITERATOR_SUBFIELD_NAME, $i));
339
341
342 if ($this->isEditElementOrderEnabled()) {
343 $tpl->setCurrentBlock('move');
344 $tpl->setVariable('UP_BUTTON', $this->renderer->render(
345 $this->glyph_factory->up()->withAction('#')
346 ));
347 $tpl->setVariable('DOWN_BUTTON', $this->renderer->render(
348 $this->glyph_factory->down()->withAction('#')
349 ));
351 }
352
353 if ($this->isEditElementOccuranceEnabled()) {
354 $tpl->setCurrentBlock('row');
355 $tpl->setVariable('ID_ADD', $this->getMultiValuePosIndexedSubFieldId($identifier, 'add', $i));
356 $tpl->setVariable('ID_REMOVE', $this->getMultiValuePosIndexedSubFieldId($identifier, 'remove', $i));
357 $tpl->setVariable('ADD_BUTTON', $this->renderer->render(
358 $this->glyph_factory->add()->withAction('#')
359 ));
360 $tpl->setVariable('REMOVE_BUTTON', $this->renderer->render(
361 $this->glyph_factory->remove()->withAction('#')
362 ));
364 }
365
366 $i++;
367 }
368
369 if (is_array($this->getSuffixes())) {
370 $suff_str = $delim = '';
371 foreach ($this->getSuffixes() as $suffix) {
372 $suff_str .= $delim . '.' . $suffix;
373 $delim = ', ';
374 }
375 $tpl->setCurrentBlock('allowed_image_suffixes');
376 $tpl->setVariable('TXT_ALLOWED_SUFFIXES', $lng->txt('file_allowed_suffixes') . ' ' . $suff_str);
378 }
379
381 $tpl->setVariable('ELEMENT_ID', $this->getPostVar());
382 $tpl->setVariable('TEXT_YES', $lng->txt('yes'));
383 $tpl->setVariable('TEXT_NO', $lng->txt('no'));
384 $tpl->setVariable('DELETE_IMAGE_HEADER', $lng->txt('delete_image_header'));
385 $tpl->setVariable('DELETE_IMAGE_QUESTION', $lng->txt('delete_image_question'));
386 $tpl->setVariable('ANSWER_TEXT', $lng->txt('answer_text'));
387 $tpl->setVariable('COMMANDS_TEXT', $lng->txt('actions'));
388
389 if (!$this->getDisabled()) {
390 $iterator_subfield_name = self::ITERATOR_SUBFIELD_NAME;
391 $image_upload_subfield_name = self::IMAGE_UPLOAD_SUBFIELD_NAME;
392
393 $init_code = <<<JS
394$.extend({}, AnswerWizardInput, IdentifiedWizardInput).init(
395 {
396 'fieldContainerSelector': '.ilWzdContainerImage',
397 'reindexingRequiredElementsSelectors': [
398 'input:hidden[name*="[{$iterator_subfield_name}]"]',
399 'input:file[id*="__{$image_upload_subfield_name}__"]',
400 'input:submit[name*="[{$this->getImageUploadCommand()}]"]',
401 'input:submit[name*="[{$this->getImageRemovalCommand()}]"]',
402 'button'
403 ],
404 'handleRowCleanUpCallback': function(rowElem) {
405 $(rowElem).find('div.imagepresentation').remove();
406 $(rowElem).find('input[type=text]').val('');
407 }
408 }
409);
410JS;
411
412 $this->tpl->addJavascript("assets/js/answerwizardinput.js");
413 $this->tpl->addJavascript("assets/js/identifiedwizardinput.js");
414 $this->tpl->addOnLoadCode($init_code);
415 }
416
417 return $tpl->get();
418 }
419
424 protected function valueHasContentImageSource($value): bool
425 {
426 return is_array($value)
427 && array_key_exists('src', $value)
428 && $value['src'] !== '';
429 }
430
435 protected function fetchContentImageSourceFromValue($value): ?string
436 {
438 return $value['src'];
439 }
440
441 return null;
442 }
443
448 protected function valueHasContentImageTitle($value): bool
449 {
450 return isset($value['title']) && strlen($value['title']);
451 }
452
453 protected function fetchContentImageTitleFromValue($value): ?string
454 {
455 if ($this->valueHasContentImageTitle($value)) {
456 return $value['title'];
457 }
458
460 }
461
465 protected function getTemplate(): ilTemplate
466 {
467 return new ilTemplate(self::RENDERING_TEMPLATE, true, true, "components/ILIAS/TestQuestionPool");
468 }
469}
renderer()
$filename
Definition: buildRTE.php:78
static getFileSizeInfo()
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addFormValuesManipulator(ilFormValuesManipulator $manipulator)
getMultiValuePostVarSubFieldPosIndexed($identifier, $sub_field_index, $position_index)
getMultiValuePosIndexedSubFieldId($identifier, $sub_field_index, $position_index)
buildMultiValueSubmitVar($identifier, $position_index, $submit_cmd)
language handling
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static prepareFormOutput($a_str, bool $a_strip=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct($a_title="", $a_postvar="")
Constructor.
onCheckInput()
Check input, strip slashes etc.
setEditElementOccuranceEnabled($editElementOccuranceEnabled)
isValidFilenameInput($filenameInput)
setEditElementOrderEnabled($editElementOrderEnabled)
setSuffixes($a_suffixes)
Set Accepted Suffixes.
special template class to simplify handling of ITX/PEAR
static virusHandling(string $a_file, string $a_orig_name='', bool $a_clean=true)
setVariable(string $variable, $value='')
Sets the given variable to the given value.
parseCurrentBlock(string $block_name=self::DEFAULT_BLOCK)
Parses the given block.
setCurrentBlock(string $part=self::DEFAULT_BLOCK)
Sets the template to the given block.
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
This is how a factory for glyphs looks like.
Definition: Factory.php:27
An entity that renders components to a string output.
Definition: Renderer.php:31
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $DIC
Definition: shib_login.php:26