Commit b98a6f7e authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'F10778UploadZIPandUnpack' into 'develop'

F10778 upload zip and unpack

See merge request !270
parents 9893fe32 fa1a8d01
Pipeline #3552 passed with stages
in 4 minutes and 26 seconds
......@@ -162,7 +162,7 @@ Upload to server, before 'save'
...............................
* If a user open's a file for upload via the browse button, that file is immediately transmitted to the server. The user
will see a turning wheel until the upload finished.
* After successfull upload the 'Browse' button disappears and the filename, plus the delete button, will be displayed (client logic).
* After successfully upload the 'Browse' button disappears and the filename, plus the delete button, will be displayed (client logic).
* The uploaded file will be checked: maxsize, mime type, check script.
* The uploaded file is still temporary. It has been renamed from '[STORE_EXTRA][<uploadSip>][FILES_TMP_NAME]' to
'[STORE_EXTRA][<uploadSip>][FILES_TMP_NAME].cached'.
......
......@@ -586,7 +586,7 @@ The `mode` is given via (in this priority):
Mode
;;;;
* *standard*:
* **standard**:
* The form will behave like defined in the form editor.
* Missing required values will a) be indicated and b) block saving the record.
......@@ -2027,7 +2027,24 @@ FormElement.parameter
* The following attributes are hard coded (can't be changed): `s|M:file|d|F`
* fileSplit, fileDestinationSplit, tableNameSplit: see :ref:`split-pdf-upload`
* *fileUnzip* - If the file is a ZIP file (only then) it will be unzipped. If no directory is given via ``fileUnzip``, the
basedir of ``fileDestination`` is taken, appended by ``unpack``.
If an unzip will be done, for each file of the archive STORE_VAR will be filled (name, path of the extracted file,
mime type, size) and the following will be triggered: *sqlValidate, slaveId, sqlBefore, sqlAfter, sqlInsert, sqlUpdate*.
Example::
fileDestination = fileadmin/file_{{id:R}}.zip
fileUnzip
sqlValidate ={{! SELECT '' FROM (SELECT '') AS fake WHERE '{{mimeType:V}}' LIKE 'application/pdf%' }}
expectRecords=1
messageFail=Unexpected filetype
# Set new
sqlAfter={{INSERT INTO Upload (pathFileName) VALUES '{{filename:V}}' }}
* `fileSplit`, `fileDestinationSplit`, `tableNameSplit`: see :ref:`split-pdf-upload`
* Excel Import: QFQ offers functionality to directly import excel data into the database. This functionality can
optionally be combined with saving the file by using the above parameters like `fileDestination`.
......@@ -2159,8 +2176,8 @@ file type.
* [jpeg] - default: `-density 150 -quality 90`
* *fileDestinationSplit* = `<pathFileName (pattern)>` - Target directory and filename pattern for the created &
split'ed files. Default <fileDestination>.split/split.<nr>.<fileSplit>.
If explicit given, respect that SVG needs a printf style for <nr>, whereas JPEG is numbered automatically. E.g. ::
split'ed files. Default <fileDestination>.split/split.<nr>.<fileSplit>.
If explicit given, respect that SVG needs a printf style for <nr>, whereas JPEG is numbered automatically. E.g. ::
[svg] fileDestinationSplit = fileadmin/protected/{{id:R}}.{{filenameBase:V}}.%02d.svg
[jpeg] fileDestinationSplit = fileadmin/protected/{{id:R}}.{{filenameBase:V}}.jpg
......
.. ==================================================
.. ==================================================
.. ==================================================
.. Header hierarchy
.. ==
.. --
.. ^^
.. ""
.. ;;
.. ,,
..
.. --------------------------------------------used to the update the records specified ------
.. Best Practice T3 reST: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/CheatSheet.html
.. Reference: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/Index.html
.. Italic *italic*
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Add Images: .. image:: ../Images/a4.jpg
..
..
.. Admonitions
.. .. note:: .. important:: .. tip:: .. warning::
.. Color: (blue) (orange) (green) (red)
..
.. Definition:
.. some text becomes strong (only one line)
.. description has to indented
.. -*- coding: utf-8 -*- with BOM.
.. include:: Includes.txt
.. _links:
Links
-----
The links to issue and the GitHub repository are maintained in the Settings.cfg.
You may want to remove this file if all important links are already handled in
Settings.cfg.
:Packagist:
https://packagist.org/packages/<username>/<extension key>
:TER:
https://typo3.org/extensions/repository/view/<extension key>
:Issues:
https://github.com/<username>/<extension key>/issues
:GitHub Repository:
https://github.com/<username>/<extension key>
:Contact:
`@<username> <https://twitter.com/your-username>`__
......@@ -87,7 +87,6 @@ This documentation is for the TYPO3 extension **qfq**.
ApplicationTest
GeneralTips
Release
Links
License
Sitemap
SearchDocs
......
......@@ -242,7 +242,7 @@ const ERROR_STORE_KEY_EXIST = 1201;
// I/O Error
const ERROR_IO_COPY = 1300;
const ERROR_IO_ZIP_OPEN = 1301;
const ERROR_IO_RMDIR = 1302;
const ERROR_IO_WRITE = 1303;
const ERROR_IO_OPEN = 1304;
......@@ -1129,6 +1129,8 @@ const FE_FILE_REPLACE_MODE = 'fileReplace'; // Flag if a) QFQ throw an error if
const FE_FILE_REPLACE_MODE_ALWAYS = 'always'; // Value for flag FE_FILE_REPLACE_MODE
const FE_FILE_MIME_TYPE_ACCEPT = 'accept'; // Comma separated list of mime types
const FE_FILE_MAX_FILE_SIZE = SYSTEM_FILE_MAX_FILE_SIZE; // Max upload file size
const FE_FILE_UNZIP = 'fileUnzip'; // 0|1|dir|{{SELECT ...}}
const FE_FILE_UNPACK_DIR = 'unpack'; // default dir if not specified
const FE_FILE_CAPTURE = 'capture'; // On a smartphone opens the camera
const FE_FILE_SPLIT = 'fileSplit';
......
......@@ -200,7 +200,7 @@ class FormAction {
$this->store->setStore($arr, STORE_LDAP, true);
}
$this->sqlValidate($fe);
HelperFormElement::sqlValidate($this->evaluate, $fe);
if ($fe[FE_TYPE] === FE_TYPE_SENDMAIL) {
$this->doSendMail($fe);
......@@ -291,57 +291,6 @@ class FormAction {
$sendMail->process($mailConfig);
}
/**
* If there is a query defined in fe.parameter.FE_SQL_VALIDATE: fire them.
* Count the selected records and compare them with fe.parameter.FE_EXPECT_RECORDS.
* If match: everything is fine, do nothing.
* Else throw \UserFormException with error message of fe.parameter.FE_MESSAGE_FAIL
*
* @param array $fe
*
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
* @throws \UserReportException
*/
private function sqlValidate(array $fe) {
// Is there something to check?
if ($fe[FE_SQL_VALIDATE] === '') {
return;
}
if ($fe[FE_EXPECT_RECORDS] === '') {
throw new \UserFormException("Missing parameter '" . FE_EXPECT_RECORDS . "'", ERROR_MISSING_EXPECT_RECORDS);
}
$expect = $this->evaluate->parse($fe[FE_EXPECT_RECORDS]);
if ($fe[FE_MESSAGE_FAIL] === '') {
throw new \UserFormException("Missing parameter '" . FE_MESSAGE_FAIL . "'", ERROR_MISSING_MESSAGE_FAIL);
}
// Do the check
$result = $this->evaluate->parse($fe[FE_SQL_VALIDATE], ROW_REGULAR);
if (!is_array($result)) {
throw new \UserFormException("Expected an array for '" . FE_SQL_VALIDATE . "', got a scalar. Please check for {{!...", ERROR_EXPECTED_ARRAY);
}
// If there is at least one record count given, who matches: return 'check succeeded'
$countRecordsArr = explode(',', $expect);
foreach ($countRecordsArr as $count) {
if (count($result) == $count) {
return; // check successfully passed
}
}
$msg = $this->evaluate->parse($fe[FE_MESSAGE_FAIL]); // Replace possible dynamic parts
// Throw user error message
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => $msg
, ERROR_MESSAGE_TO_DEVELOPER => 'validate() failed']), ERROR_REPORT_FAILED_ACTION);
}
/**
* Process slaveId, sqlBefore, sqlInsert|sqlUpdate|sqlDelete, sqlAfter.
* flagFeAction=false: for Native Elements
......
......@@ -101,6 +101,8 @@ class HelperFile {
/**
* Returns an array with filestat information to $pathFileName
* - mimeType
* - fileSize
*
* @param $pathFileName
* @return array
......@@ -540,5 +542,43 @@ class HelperFile {
return $pre . $separator . $post;
}
/**
* Translates ZIP error codes to text.
*
* @param $errno
* @return string
*/
public static function zipFileErrMsg($errno) {
// using constant name as a string to make this function PHP4 compatible
$zipFileFunctionsErrors = array(
'ZIPARCHIVE::ER_MULTIDISK' => 'Multi-disk zip archives not supported.',
'ZIPARCHIVE::ER_RENAME' => 'Renaming temporary file failed.',
'ZIPARCHIVE::ER_CLOSE' => 'Closing zip archive failed',
'ZIPARCHIVE::ER_SEEK' => 'Seek error',
'ZIPARCHIVE::ER_READ' => 'Read error',
'ZIPARCHIVE::ER_WRITE' => 'Write error',
'ZIPARCHIVE::ER_CRC' => 'CRC error',
'ZIPARCHIVE::ER_ZIPCLOSED' => 'Containing zip archive was closed',
'ZIPARCHIVE::ER_NOENT' => 'No such file.',
'ZIPARCHIVE::ER_EXISTS' => 'File already exists',
'ZIPARCHIVE::ER_OPEN' => 'Can\'t open file',
'ZIPARCHIVE::ER_TMPOPEN' => 'Failure to create temporary file.',
'ZIPARCHIVE::ER_ZLIB' => 'Zlib error',
'ZIPARCHIVE::ER_MEMORY' => 'Memory allocation failure',
'ZIPARCHIVE::ER_CHANGED' => 'Entry has been changed',
'ZIPARCHIVE::ER_COMPNOTSUPP' => 'Compression method not supported.',
'ZIPARCHIVE::ER_EOF' => 'Premature EOF',
'ZIPARCHIVE::ER_INVAL' => 'Invalid argument',
'ZIPARCHIVE::ER_NOZIP' => 'Not a zip archive',
'ZIPARCHIVE::ER_INTERNAL' => 'Internal error',
'ZIPARCHIVE::ER_INCONS' => 'Zip archive inconsistent',
'ZIPARCHIVE::ER_REMOVE' => 'Can\'t remove file',
'ZIPARCHIVE::ER_DELETED' => 'Entry has been deleted',
);
return $zipFileFunctionsErrors[$errno] ?? 'unknown';
}
}
......@@ -8,6 +8,7 @@
namespace IMATHUZH\Qfq\Core\Helper;
use IMATHUZH\Qfq\Core\Evaluate;
use IMATHUZH\Qfq\Core\Store\Store;
......@@ -37,7 +38,7 @@ class HelperFormElement {
*/
public static function explodeParameterInArrayElements(array &$elements, $keyName) {
foreach ($elements AS $key => $element) {
foreach ($elements as $key => $element) {
self::explodeParameter($element, $keyName);
$elements[$key] = $element;
}
......@@ -58,7 +59,7 @@ class HelperFormElement {
// Do not add FE_SLAVE_ID - it's necessary to detect if a value is given or not.
$default = [FE_SQL_BEFORE => '', FE_SQL_INSERT => '', FE_SQL_UPDATE => '', FE_SQL_DELETE => '', FE_SQL_AFTER => ''];
foreach ($elements AS $key => $element) {
foreach ($elements as $key => $element) {
$elements[$key][FE_TG_INDEX] = 0;
unset($elements[$key][FE_ADMIN_NOTE]);
// $elements[$key][FE_DATA_REFERENCE] = '';
......@@ -91,7 +92,7 @@ class HelperFormElement {
if (!$flagAllowOverwrite) {
// Check if some of the exploded keys conflict with existing keys
$checkKeys = array_keys($arr);
foreach ($checkKeys AS $checkKey) {
foreach ($checkKeys as $checkKey) {
if (!empty($element[$checkKey])) {
self::$store = Store::getInstance();
self::$store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($element), STORE_SYSTEM);
......@@ -861,5 +862,55 @@ EOF;
return '<div class="help-block with-errors hidden"></div>';
}
/**
* If there is a query defined in fe.parameter.FE_SQL_VALIDATE: fire them.
* Count the selected records and compare them with fe.parameter.FE_EXPECT_RECORDS.
* If match: everything is fine, do nothing.
* Else throw \UserFormException with error message of fe.parameter.FE_MESSAGE_FAIL
*
* @param array $fe
* @param Evaluate $evaluate
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
* @throws \UserReportException
*/
public static function sqlValidate(Evaluate $evaluate, array $fe) {
// Is there something to check?
if ($fe[FE_SQL_VALIDATE] === '') {
return;
}
if ($fe[FE_EXPECT_RECORDS] === '') {
throw new \UserFormException("Missing parameter '" . FE_EXPECT_RECORDS . "'", ERROR_MISSING_EXPECT_RECORDS);
}
$expect = $evaluate->parse($fe[FE_EXPECT_RECORDS]);
if ($fe[FE_MESSAGE_FAIL] === '') {
throw new \UserFormException("Missing parameter '" . FE_MESSAGE_FAIL . "'", ERROR_MISSING_MESSAGE_FAIL);
}
// Do the check
$result = $evaluate->parse($fe[FE_SQL_VALIDATE], ROW_REGULAR);
if (!is_array($result)) {
throw new \UserFormException("Expected an array for '" . FE_SQL_VALIDATE . "', got a scalar. Please check for {{!...", ERROR_EXPECTED_ARRAY);
}
// If there is at least one record count given, who matches: return 'check succeeded'
$countRecordsArr = explode(',', $expect);
foreach ($countRecordsArr as $count) {
if (count($result) == $count) {
return; // check successfully passed
}
}
$msg = $evaluate->parse($fe[FE_MESSAGE_FAIL]); // Replace possible dynamic parts
// Throw user error message
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => $msg
, ERROR_MESSAGE_TO_DEVELOPER => "validate() failed.\nSQL Raw: " . $fe[FE_SQL_VALIDATE]])
, ERROR_REPORT_FAILED_ACTION);
}
}
\ No newline at end of file
......@@ -20,6 +20,7 @@ use IMATHUZH\Qfq\Core\Helper\Support;
use IMATHUZH\Qfq\Core\Store\FillStoreForm;
use IMATHUZH\Qfq\Core\Store\Sip;
use IMATHUZH\Qfq\Core\Store\Store;
use ZipArchive;
/**
* Class Save
......@@ -254,7 +255,7 @@ class Save {
$formValues = $this->createEmptyTemplateGroupElements($formValues);
// Iterate over all table.columns. Built an assoc array $newValues.
foreach ($tableColumns AS $column) {
foreach ($tableColumns as $column) {
// Never save a predefined 'id': autoincrement values will be given by database..
if ($column === COLUMN_ID) {
......@@ -408,7 +409,7 @@ class Save {
*/
private function isColumnUploadField($feName) {
foreach ($this->feSpecNative AS $formElement) {
foreach ($this->feSpecNative as $formElement) {
if ($formElement[FE_NAME] === $feName && $formElement[FE_TYPE] == FE_TYPE_UPLOAD)
return true;
}
......@@ -501,12 +502,22 @@ class Save {
$sip = new Sip(false);
$newValues = array();
$vars = array();
$flagDoUnzip = false;
$formValues = $this->store->getStore(STORE_FORM);
$primaryRecord = $this->store->getStore(STORE_RECORD); // necessary to check if the current formElement exist as a column of the primary table.
foreach ($this->feSpecNative AS $formElement) {
// Upload - Take care the necessary target directories exist.
$cwd = getcwd();
$sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM);
if ($cwd === false || $sitePath === false || !HelperFile::chdir($sitePath)) {
throw new \UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_TO_DEVELOPER => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
ERROR_IO_CHDIR);
}
foreach ($this->feSpecNative as $formElement) {
// skip non upload formElements
if ($formElement[FE_TYPE] != FE_TYPE_UPLOAD) {
continue;
......@@ -523,7 +534,34 @@ class Save {
}
$column = $formElement[FE_NAME];
$statusUpload = $this->store->getVar($formValues[$column] ?? '', STORE_EXTRA);
// Get file stats
$vars = array();
$vars[VAR_FILE_SIZE] = $statusUpload[FILES_SIZE] ?? '';
$vars[VAR_FILE_MIME_TYPE] = $statusUpload[FILES_TYPE] ?? '';
// Check for 'unzip'.
if (isset($formElement[FE_FILE_UNZIP])
&& $formElement[FE_FILE_UNZIP] != '0'
&& $vars[VAR_FILE_MIME_TYPE] == 'application/zip') {
$flagDoUnzip = true;
}
// Do upload
$pathFileName = $this->doUpload($formElement, ($formValues[$column] ?? ''), $sip, $modeUpload);
if ($flagDoUnzip && $pathFileName != '') {
if ($formElement[FE_FILE_UNZIP] == '' || $formElement[FE_FILE_UNZIP] == '1') {
// Set default dir.
$formElement[FE_FILE_UNZIP] = HelperFile::joinPathFilename(dirname($pathFileName), FE_FILE_UNPACK_DIR);
}
// Backup STORE_VAR - will be changed in doUnzip()
$tmpStoreVar = $this->store->getStore(STORE_VAR);
$this->doUnzip($formElement, $pathFileName);
// Restore STORE_VAR
$this->store->setStore($tmpStoreVar, STORE_VAR, true);
}
if ($modeUpload == UPLOAD_MODE_DELETEOLD && $pathFileName == '') {
$pathFileNameTmp = ''; // see '4'
......@@ -540,15 +578,15 @@ class Save {
// No new upload and no existing: take care to remove previous upload file statistics.
$this->store->unsetVar(VAR_FILE_MIME_TYPE, STORE_VAR);
$this->store->unsetVar(VAR_FILE_SIZE, STORE_VAR);
$vars[VAR_FILE_SIZE] = 0;
$vars[VAR_FILE_MIME_TYPE] = '';
} else {
$vars = HelperFile::getFileStat($pathFileNameTmp);
$this->store->appendToStore($vars, STORE_VAR);
}
// If given: fire a sqlBefore query
$this->evaluate->parse($formElement[FE_SQL_BEFORE]);
if (!$flagDoUnzip) {
$this->evaluate->parse($formElement[FE_SQL_BEFORE]);
}
// Upload Type: Simple or Advanced
// If (isset($primaryRecord[$column])) { - see #5048 - isset does not deal correctly with NULL!
......@@ -567,22 +605,101 @@ class Save {
}
} elseif (isset($formElement[FE_IMPORT_TO_TABLE]) && !isset($formElement[FE_SLAVE_ID])) {
// Excel import on nonexisting column -> no upload
} elseif ($flagDoUnzip) {
// If ZIP and advanced upload: process it not here but via doUnzip.
} else {
// 'Advanced Upload'
$this->doUploadSlave($formElement, $modeUpload);
}
// If given: fire a sqlAfter query
$this->evaluate->parse($formElement[FE_SQL_AFTER]);
if (!$flagDoUnzip) {
$this->evaluate->parse($formElement[FE_SQL_AFTER]);
}
}
// Clean up
HelperFile::chdir($cwd);
// Only used in 'Simple Upload'
if (count($newValues) > 0) {
$this->updateRecord($this->formSpec[F_TABLE_NAME], $newValues, $recordId, $this->formSpec[F_PRIMARY_KEY]);
}
}
/**
* Unzip $pathFileName to $formElement[FE_FILE_UNZIP]. Before final extract, fire FE_SQL_VALIDATE.
* For each file in ZIP:
* - Fill STORE_VAR with VAR_FILENAME, VAR_FILENAME_ONLY, VAR_FILENAME_BASE, VAR_FILENAME_EXT, VAR_FILE_MIME_TYPE, VAR_FILE_SIZE.
* - Fire $formElement[FE_SQL_VALIDATE]
* - Fire FE_SLAVE_ID, FE_SQL_BEFORE, FE_SQL_INSERT, FE_SQL_UPDATE, FE_SQL_DELETE, FE_SQL_AFTER
*
* @param array $formElement
* @param string $pathFileName
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
* @throws \UserReportException
*/
private function doUnzip(array $formElement, $pathFileName) {
if (!is_readable($pathFileName)) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Open ZIP file failed",
ERROR_MESSAGE_TO_DEVELOPER => "File: " . $pathFileName]),
ERROR_IO_ZIP_OPEN);
}
$zip = new ZipArchive();
$res = $zip->open($pathFileName);
if ($res !== true) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Open ZIP file failed" . HelperFile::zipFileErrMsg($res),
ERROR_MESSAGE_TO_DEVELOPER => "File: " . $pathFileName]), ERROR_IO_ZIP_OPEN);
}
// Extract
if (false === $zip->extractTo($formElement[FE_FILE_UNZIP])) {
throw new \UserFormException("Failed to extract ZIP.", ERROR_IO_ZIP_OPEN);
}
// Do sqlValidate() - to get mime type of zipped items, the archive has already been extracted.
if (!empty($formElement[FE_SQL_VALIDATE])) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$itemPathFileName = HelperFile::joinPathFilename($formElement[FE_FILE_UNZIP], $stat['name']);
$this->store->appendToStore(HelperFile::getFileStat($itemPathFileName), STORE_VAR);
$this->store->appendToStore(HelperFile::pathinfo($itemPathFileName), STORE_VAR);
HelperFormElement::sqlValidate($this->evaluate, $formElement);
}
}
// Process
if (!isset($formElement[FE_SLAVE_ID])) {
$formElement[FE_SLAVE_ID] = '';
}
if (!empty($formElement[FE_SLAVE_ID] . $formElement[FE_SQL_BEFORE] . $formElement[FE_SQL_INSERT] .
$formElement[FE_SQL_UPDATE] . $formElement[FE_SQL_DELETE] . $formElement[FE_SQL_AFTER])) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$itemPathFileName = HelperFile::joinPathFilename($formElement[FE_FILE_UNZIP], $stat['name']);
$this->store->appendToStore(HelperFile::getFileStat($itemPathFileName), STORE_VAR);
$this->store->appendToStore(HelperFile::pathinfo($itemPathFileName), STORE_VAR);
$this->evaluate->parse($formElement[FE_SQL_BEFORE]);
$this->doUploadSlave($formElement, UPLOAD_MODE_NEW);
$this->evaluate->parse($formElement[FE_SQL_AFTER]);
}
}
// Close Zip
if (false === $zip->close()) {
throw new \UserFormException("Failed to close ZIP.", ERROR_IO_ZIP_OPEN);
}
}
/**
* Process all Upload FormElements for the given $recordId.
* After processing, &$formValues will be updated with the final filename.
......@@ -592,7 +709,7 @@ class Save {
*/
public function processAllImageCutFE() {
foreach ($this->feSpecNative AS $formElement) {
foreach ($this->feSpecNative as $formElement) {
// skip non upload formElements
if ($formElement[FE_TYPE] != FE_TYPE_IMAGE_CUT) {
continue;
......@@ -631,7 +748,7 @@ class Save {
$flagAllRequiredGiven = 1;
foreach ($this->feSpecNative AS $key => $formElement) {
foreach ($this->feSpecNative as $key => $formElement) {
// Do not check retype slave FE.
if (isset($formElement[FE_RETYPE_SOURCE_NAME])) {
......@@ -748,26 +865,26 @@ class Save {
* Process upload for the given Formelement. If necessary, delete a previous uploaded file.
* Calculate the final path/filename and move the file to the new location.
*
* Check also: doc/CODING.md
* Check also: Documentation-develop/CODING.md
*
* @param array $formElement FormElement 'upload'
* @param string $sipUpload SIP
* @param Sip $sip
* @param string $modeUpload UPLOAD_MODE_UNCHANGED | UPLOAD_MODE_NEW | UPLOAD_MODE_DELETEOLD |
* UPLOAD_MODE_DELETEOLD_NEW
*
* @return false|string New pathFilename or false on error
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
* @throws \UserReportException
* @throws \PhpOffice\PhpSpreadsheet\Exception
* @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
* @throws \UserFormException
* @throws \UserReportException
* @internal param $recordId
*/
private function doUpload($formElement, $sipUpload, Sip $sip, &$modeUpload) {
$flagDelete = false;
$modeUpload = UPLOAD_MODE_UNCHANGED;
$pathFileName = '';
// Status information about upload file
$statusUpload = $this->store->getVar($sipUpload, STORE_EXTRA);
......@@ -781,15 +898,6 @@ class Save {
$this->doImport($formElement, $tmpFile);
}
// Upload - Take care the necessary target directories exist.
$cwd = getcwd();
$sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM);