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
633c1a3b
Commit
633c1a3b
authored
Jun 25, 2020
by
Carsten Rose
Browse files
Merge remote-tracking branch 'origin/develop' into develop
parents
669e6bff
b98a6f7e
Pipeline
#3562
passed with stages
in 4 minutes and 55 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Documentation-develop/CODING.md
View file @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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 @
669e6bff
.. ==================================================
.. ==================================================
.. ==================================================
.. 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 @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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 @
633c1a3b
...
...
@@ -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
);