Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
typo3
qfq
Commits
b98a6f7e
Commit
b98a6f7e
authored
Jun 24, 2020
by
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
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Documentation-develop/CODING.md
View file @
b98a6f7e
...
...
@@ -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 successfull
y
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'.
...
...
Documentation/Form.rst
View file @
b98a6f7e
...
...
@@ -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
...
...
Documentation/Links.rst
deleted
100644 → 0
View file @
9893fe32
.. ==================================================
.. ==================================================
.. ==================================================
.. 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>`__
Documentation/index.rst
View file @
b98a6f7e
...
...
@@ -87,7 +87,6 @@ This documentation is for the TYPO3 extension **qfq**.
ApplicationTest
GeneralTips
Release
Links
License
Sitemap
SearchDocs
...
...
extension/Classes/Core/Constants.php
View file @
b98a6f7e
...
...
@@ -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'
;
...
...
extension/Classes/Core/Form/FormAction.php
View file @
b98a6f7e
...
...
@@ -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
...
...
extension/Classes/Core/Helper/HelperFile.php
View file @
b98a6f7e
...
...
@@ -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'
;
}
}
extension/Classes/Core/Helper/HelperFormElement.php
View file @
b98a6f7e
...
...
@@ -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.
\n
SQL Raw: "
.
$fe
[
FE_SQL_VALIDATE
]])
,
ERROR_REPORT_FAILED_ACTION
);
}
}
\ No newline at end of file
extension/Classes/Core/Save.php
View file @
b98a6f7e
...
...
@@ -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:
d
oc/CODING.md
* Check also:
D
oc
umentation-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
);