Skip to content
GitLab
Menu
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
b6cfd023
Commit
b6cfd023
authored
Jul 09, 2018
by
Carsten Rose
Browse files
F4922 / Excel Import: First, untested, version of generic excel export
parent
c9fb2a67
Pipeline
#670
passed with stage
in 1 minute and 34 seconds
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
b6cfd023
...
...
@@ -22,6 +22,7 @@ maintainer-clean:
archive
:
clean qfq.zip
qfq.zip
:
cd
extension/Resources/Private/vendor/phpoffice
;
rm
-rf
phpspreadsheet/
{
C
*
,bin,c
*
,d
*
,m
*
,p
*
,sa
*
,.g
*
,.p
*
,.s
*
,.t
*
}
cd
extension
;
zip
-r
../
$@
$(EXTENSION_CONTENT)
clean
:
...
...
extension/qfq/api/download.php
View file @
b6cfd023
...
...
@@ -26,7 +26,7 @@ $error = '';
try
{
try
{
$download
=
new
\
qfq\
Download
();
$download
=
new
Download
();
// If all is fine: process() will output file via print() !!
$error
=
$download
->
process
(
STORE_SIP
,
OUTPUT_MODE_DIRECT
);
...
...
extension/qfq/external/AutoCron.php
View file @
b6cfd023
...
...
@@ -17,6 +17,7 @@ require_once(__DIR__ . '/../qfq/exceptions/ShellException.php');
require_once
(
__DIR__
.
'/../qfq/Evaluate.php'
);
require_once
(
__DIR__
.
'/../qfq/report/SendMail.php'
);
require_once
(
__DIR__
.
'/../qfq/helper/Support.php'
);
require_once
(
__DIR__
.
'/../qfq/helper/DownloadPage.php'
);
/**
* Class AutoCron
...
...
@@ -154,21 +155,9 @@ class AutoCron {
if
(
!
empty
(
$job
[
AUTOCRON_CONTENT
]))
{
// If the URL does not start with 'http...': prefix with the site config.
if
(
substr
(
$job
[
AUTOCRON_CONTENT
],
0
,
4
)
!=
'http'
)
{
// We need to prefix
$baseUrl
=
$this
->
store
->
getVar
(
SYSTEM_BASE_URL
,
STORE_SYSTEM
);
$job
[
AUTOCRON_CONTENT
]
=
$baseUrl
.
$job
[
AUTOCRON_CONTENT
];
}
$baseUrl
=
$this
->
store
->
getVar
(
SYSTEM_BASE_URL
,
STORE_SYSTEM
);
// Download page
$ctx
=
array
(
"ssl"
=>
array
(
"verify_peer"
=>
false
,
"verify_peer_name"
=>
false
,
),
);
$page
=
file_get_contents
(
$job
[
AUTOCRON_CONTENT
],
false
,
stream_context_create
(
$ctx
));
$page
=
DownloadPage
::
getContent
(
$job
[
AUTOCRON_CONTENT
],
$baseUrl
);
if
(
$page
===
false
)
{
$job
[
AUTOCRON_LAST_STATUS
]
=
htmlspecialchars
(
AUTOCRON_STATUS_ERROR
.
'failed to fetch "'
.
$job
[
AUTOCRON_CONTENT
]
.
'"'
);
...
...
extension/qfq/qfq/Constants.php
View file @
b6cfd023
...
...
@@ -258,6 +258,9 @@ const ERROR_DOWNLOAD_UNEXPECTED_MIME_TYPE = 1703;
const
ERROR_DOWNLOAD_UNEXPECTED_NUMBER_OF_SOURCES
=
1704
;
const
ERROR_DOWNLOAD_FILE_NOT_READABLE
=
1705
;
// Excel
const
ERROR_EXCEL_POSITION_ARGUMENT_EMPTY
=
1800
;
// KeyValueParser
const
ERROR_KVP_VALUE_HAS_NO_KEY
=
1900
;
...
...
@@ -1114,6 +1117,8 @@ const HTML_INPUT_TYPE_NUMBER = 'number';
const
SHEBANG_REPORT
=
'#!report'
;
CONST
TOKEN_COMMENT
=
'#'
;
// SUPPORT
const
PARAM_T3_ALL
=
't3 all'
;
const
PARAM_T3_NO_ID
=
"t3 no id"
;
...
...
@@ -1336,6 +1341,19 @@ const JSON_TEXT = 'text';
const
OUTPUT_MODE_DIRECT
=
'direct'
;
const
OUTPUT_MODE_FILE
=
'file'
;
const
EXCEL_WORKSHEET
=
'worksheet'
;
const
EXCEL_MODE
=
'mode'
;
const
EXCEL_MODE_INSERT
=
'insert'
;
const
EXCEL_MODE_OVERWRITE
=
'overwrite'
;
const
EXCEL_POSITION
=
'position'
;
const
EXCEL_ROW
=
'row'
;
const
EXCEL_STRING
=
'string'
;
const
EXCEL_NUMBER
=
'number'
;
const
EXCEL_CURRENCY
=
'currency'
;
const
EXCEL_DATE
=
'date'
;
const
EXCEL_DATETIME
=
'datetime'
;
const
EXCEL_TIME
=
'time'
;
const
MONITOR_TAIL_DEFAULT
=
30
;
const
MONITOR_APPEND_DEFAULT
=
0
;
const
MONITOR_INTERVAL_DEFAULT
=
1000
;
...
...
@@ -1520,4 +1538,5 @@ const DND_HOVER_POSITION = 'hoverPosition';
const
DND_COLUMN_ID
=
'id'
;
const
DND_COLUMN_ORD
=
'ord'
;
const
DND_COLUMN_ORD_NEW
=
'ordNew'
;
const
DND_DATA_DND_API
=
'data-dnd-api'
;
\ No newline at end of file
const
DND_DATA_DND_API
=
'data-dnd-api'
;
extension/qfq/qfq/helper/DownloadPage.php
0 → 100644
View file @
b6cfd023
<?php
/**
* Created by PhpStorm.
* User: crose
* Date: 7/8/18
* Time: 11:17 PM
*/
namespace
qfq
;
/**
* Class DownloadPage
* @package qfq
*/
class
DownloadPage
{
/**
* Retrieve the content of the given page and returns them.
* $page
*
* @param string $page - Full URL like 'https://example.com' or T3 specific like 'export&s=badcaffee1234'
* @param string $baseUrl - baserUrl from Configfile
* @return bool|string
*/
public
static
function
getContent
(
$page
,
$baseUrl
)
{
if
(
empty
(
$page
))
{
return
false
;
}
if
(
substr
(
$page
,
0
,
4
)
!=
'http'
)
{
if
(
empty
(
$baseUrl
))
{
return
false
;
}
// We need to prefix
$page
=
$baseUrl
.
$page
;
}
// Download page
$ctx
=
array
(
"ssl"
=>
array
(
"verify_peer"
=>
false
,
"verify_peer_name"
=>
false
,
),
);
return
file_get_contents
(
$page
,
false
,
stream_context_create
(
$ctx
));
}
}
\ No newline at end of file
extension/qfq/qfq/helper/HelperFile.php
View file @
b6cfd023
...
...
@@ -35,6 +35,14 @@ class HelperFile {
}
}
/**
* Returns a uniqe (use for temporary) filename, prefixed with QFQ TMP_FILE_PREFIX
*
* @return bool|string
*/
public
static
function
tempnam
(){
return
tempnam
(
sys_get_temp_dir
(),
TMP_FILE_PREFIX
);
}
/**
* Check against standard QFQ Temp location. If it is a Qfq Temp location, return true, else false.
...
...
extension/qfq/qfq/helper/OnString.php
View file @
b6cfd023
...
...
@@ -84,4 +84,16 @@ class OnString {
return
$str
;
}
/**
* Split an Excel position string line 'A1' oder 'ACD4567' to [ 'A', '1'], resp. [ 'ACD', '4567' ]
*
* @param $pos
* @return mixed
*/
public
static
function
splitExcelPos
(
$pos
){
preg_match_all
(
'/(\w)|(\d)/'
,
$pos
,
$matches
);
return
$matches
;
}
}
extension/qfq/qfq/report/Download.php
View file @
b6cfd023
...
...
@@ -23,6 +23,9 @@ require_once(__DIR__ . '/../report/Html2Pdf.php');
require_once
(
__DIR__
.
'/Thumbnail.php'
);
require_once
(
__DIR__
.
'/Monitor.php'
);
require_once
(
__DIR__
.
'/../exceptions/DownloadException.php'
);
require_once
(
__DIR__
.
'/Excel.php'
);
require_once
(
__DIR__
.
'/../helper/DownloadPage.php'
);
//require_once(__DIR__ . '/../Evaluate.php');
//require_once(__DIR__ . '/../helper/KeyValueStringParser.php');
//
...
...
@@ -120,8 +123,7 @@ class Download {
break
;
}
$concatFile
=
tempnam
(
sys_get_temp_dir
(),
TMP_FILE_PREFIX
);
$concatFile
=
HelperFile
::
tempnam
();
if
(
false
===
$concatFile
)
{
throw
new
DownloadException
(
'Error creating output file.'
,
ERROR_DOWNLOAD_CREATE_NEW_FILE
);
}
...
...
@@ -202,16 +204,20 @@ class Download {
}
/**
* Interprets $element and fetches corresponding content as file.
* Interprets $element and fetches corresponding content
, either
as
a
file
or the content in a variable
.
*
* @param string $element - U:id=myExport&r=12, u:http://www.nzz.ch/issue?nr=21, f:fileadmin/sample.pdf
*
* @param string $downloadMode - DOWNLOAD_MODE_EXCEL | ....
* @param string $tmpData - With $downloadMod=DOWNLOAD_MODE_EXCEL, this contains the rendered code from the give T3 page.
* @return string filename - already ready or fresh exported. Fresh exported needs to be deleted later.
* @throws CodeException
* @throws DownloadException
* @throws
\e
xception
* @throws
UserFormE
xception
*/
private
function
getElement
(
$element
)
{
private
function
getElement
(
$element
,
$downloadMode
,
&
$tmpData
)
{
$filename
=
''
;
$arr
=
explode
(
':'
,
$element
,
2
);
if
(
count
(
$arr
)
!=
2
)
{
throw
new
DownloadException
(
'Missing parameter for "'
.
$element
.
'"'
,
ERROR_MISSING_REQUIRED_PARAMETER
);
...
...
@@ -224,7 +230,13 @@ class Download {
case
TOKEN_URL
:
case
TOKEN_URL_PARAM
:
case
TOKEN_PAGE
:
$filename
=
$this
->
html2pdf
->
page2pdf
(
$token
,
$value
);
if
(
$downloadMode
==
DOWNLOAD_MODE_EXCEL
)
{
$baseUrl
=
$this
->
store
->
getVar
(
SYSTEM_BASE_URL
,
STORE_SYSTEM
);
$tmpData
=
DownloadPage
::
getContent
(
$value
,
$baseUrl
);
}
else
{
$filename
=
$this
->
html2pdf
->
page2pdf
(
$token
,
$value
);
}
break
;
case
TOKEN_FILE
:
...
...
@@ -250,7 +262,7 @@ class Download {
*/
private
function
zipFiles
(
array
$files
)
{
$zipFile
=
tempnam
(
sys_get_temp_dir
(),
TMP_FILE_PREFIX
);
$zipFile
=
HelperFile
::
tempnam
(
);
if
(
false
===
$zipFile
)
{
throw
new
DownloadException
(
"Error creating output file."
,
ERROR_DOWNLOAD_CREATE_NEW_FILE
);
}
...
...
@@ -264,15 +276,14 @@ class Download {
$len
=
strlen
(
TMP_FILE_PREFIX
);
$ii
=
1
;
foreach
(
$files
AS
$filename
)
{
$local
n
ame
=
substr
(
$filename
,
strrpos
(
$filename
,
'/'
)
+
1
);
$local
N
ame
=
substr
(
$filename
,
strrpos
(
$filename
,
'/'
)
+
1
);
if
(
substr
(
$local
n
ame
,
0
,
$len
)
==
TMP_FILE_PREFIX
)
{
$local
n
ame
=
'file-'
.
$ii
;
if
(
substr
(
$local
N
ame
,
0
,
$len
)
==
TMP_FILE_PREFIX
)
{
$local
N
ame
=
'file-'
.
$ii
;
$ii
++
;
}
// $localname = $this->targetFilenameExtension($filename, $localname, $mimetype);
$zip
->
addFile
(
$filename
,
$local
n
ame
);
$zip
->
addFile
(
$filename
,
$local
N
ame
);
}
$zip
->
close
();
...
...
@@ -280,8 +291,8 @@ class Download {
}
/**
*
exportFilename=
<new filename>
*
mode=
file | pdf | excel | thumbnail | monitor - default is 'file' in case of only one or 'pdf' in case of multiple sources.
*
$vars[DOWNLOAD_EXPORT_FILENAME] - Optional. '
<new filename>
'
*
$vars[DOWNLOAD_MODE] - Optional.
file | pdf | excel | thumbnail | monitor - default is
a)
'file' in case of only one or
b)
'pdf' in case of multiple sources.
* HTML to PDF | Excel
* <i>_id=<Typo3 pageId>
* <i>_<key>=<value i>
...
...
@@ -293,6 +304,7 @@ class Download {
* @param string $outputMode OUTPUT_MODE_DIRECT | OUTPUT_MODE_FILE
* @return string Filename of the generated file. The filename only points to a real existing filename with $outputMode=OUTPUT_MODE_FILE
* @throws CodeException
* @throws DbException
* @throws DownloadException
* @throws UserFormException
* @throws UserReportException
...
...
@@ -323,9 +335,14 @@ class Download {
$elements
=
explode
(
PARAM_DELIMITER
,
$vars
[
SIP_DOWNLOAD_PARAMETER
]);
// Get all files
// Get all files / content
$tmpData
=
array
();
foreach
(
$elements
as
$element
)
{
$tmpFiles
[]
=
$this
->
getElement
(
$element
);
$data
=
''
;
$tmpFiles
[]
=
$this
->
getElement
(
$element
,
$downloadMode
,
$data
);
if
(
!
empty
(
$data
)){
$tmpData
[]
=
$data
;
}
}
// Export, Concat File(s)
...
...
@@ -338,7 +355,15 @@ class Download {
break
;
case
DOWNLOAD_MODE_EXCEL
:
throw
new
DownloadException
(
"Not implemented:
$downloadMode
"
,
ERROR_NOT_IMPLEMENTED
);
$excel
=
new
Excel
();
$filename
=
$excel
->
process
(
$tmpFiles
,
$tmpData
);
if
(
empty
(
$vars
[
DOWNLOAD_EXPORT_FILENAME
]))
{
if
(
HelperFile
::
isQfqTemp
(
$filename
))
{
$vars
[
DOWNLOAD_EXPORT_FILENAME
]
=
DOWNLOAD_OUTPUT_FILENAME
.
".xlsx"
;
}
else
{
$vars
[
DOWNLOAD_EXPORT_FILENAME
]
=
basename
(
$filename
);
}
}
break
;
case
DOWNLOAD_MODE_FILE
:
...
...
@@ -349,7 +374,9 @@ class Download {
break
;
case
DOWNLOAD_MODE_PDF
:
$filename
=
$this
->
concatPdfFiles
(
$tmpFiles
);
// try to find a meaningful filename
if
(
empty
(
$vars
[
DOWNLOAD_EXPORT_FILENAME
]))
{
if
(
count
(
$tmpFiles
)
>
1
)
{
...
...
@@ -377,7 +404,7 @@ class Download {
case
OUTPUT_MODE_DIRECT
:
$this
->
outputFile
(
$filename
,
$vars
[
DOWNLOAD_EXPORT_FILENAME
]);
HelperFile
::
cleanTempFiles
([
$filename
]);
$filename
=
''
;
$filename
=
''
;
break
;
default
:
...
...
@@ -410,6 +437,7 @@ class Download {
*
* @return string
* @throws CodeException
* @throws DbException
* @throws DownloadException
* @throws UserFormException
* @throws UserReportException
...
...
extension/qfq/qfq/report/Excel.php
0 → 100644
View file @
b6cfd023
<?php
/**
* Created by PhpStorm.
* User: crose
* Date: 8/7/18
* Time: 11:32 AM
*
* Check: CODING.md > Download
*/
namespace
qfq
;
//use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
require_once
(
__DIR__
.
'/../Constants.php'
);
//require_once(__DIR__ . '/../store/Session.php');
//require_once(__DIR__ . '/../store/Store.php');
//require_once(__DIR__ . '/../helper/OnArray.php');
//require_once(__DIR__ . '/../helper/Logger.php');
//require_once(__DIR__ . '/../helper/Sanitize.php');
require_once
(
__DIR__
.
'/../helper/HelperFile.php'
);
//require_once(__DIR__ . '/../report/Html2Pdf.php');
//require_once(__DIR__ . '/Thumbnail.php');
//require_once(__DIR__ . '/Monitor.php');
require_once
(
__DIR__
.
'/../exceptions/DownloadException.php'
);
//require_once(__DIR__ . '/../Evaluate.php');
//require_once(__DIR__ . '/../helper/KeyValueStringParser.php');
//
require
__DIR__
.
'/../../../Resources/Private/vendor/autoload.php'
;
use
PhpOffice\PhpSpreadsheet\Spreadsheet
;
use
PhpOffice\PhpSpreadsheet\Writer\Xlsx
;
const
COLUMN
=
0
;
const
ROW
=
1
;
/**
* Class Excel
* @package qfq
*/
class
Excel
{
/**
* @param array $files
* @param array $data
* @return string
* @throws downloadException
*/
public
function
process
(
array
$files
,
array
$data
)
{
// Check that there are some sources
if
(
empty
(
$files
)
&&
empty
(
$data
))
{
throw
new
downloadException
(
"No source found to offer to download"
,
ERROR_DOWNLOAD_NOTHING_TO_DO
);
}
// Check if there are only File(s) given: return them.
if
(
empty
(
$data
))
{
if
(
count
(
$files
)
==
1
)
{
return
$files
[
0
];
// Return the given file.
}
else
{
throw
new
downloadException
(
"Only one source file per Excel download supported"
,
ERROR_DOWNLOAD_UNEXPECTED_NUMBER_OF_SOURCES
);
}
}
// Use Template or NEW
if
(
isset
(
$files
[
0
]))
{
// Open template
$spreadsheet
=
\
PhpOffice\PhpSpreadsheet\IOFactory
::
load
(
$files
[
0
]);
}
else
{
// Create new
$spreadsheet
=
new
Spreadsheet
();
}
// Iterate over all sources.
foreach
(
$data
as
$page
)
{
$spreadsheet
=
$this
->
fillSpreadsheet
(
$spreadsheet
,
$page
);
}
$filename
=
HelperFile
::
tempnam
();
$writer
=
new
Xlsx
(
$spreadsheet
);
$writer
->
save
(
$filename
);
return
$filename
;
}
/**
* @param Spreadsheet $spreadsheet
* @param string $data
* @return Spreadsheet
* @throws downloadException
*/
private
function
fillSpreadsheet
(
Spreadsheet
$spreadsheet
,
$data
)
{
$worksheet
=
$spreadsheet
->
getActiveSheet
();
$pos
=
'A1'
;
$tmpArr
=
OnString
::
splitExcelPos
(
$pos
);
$posColumn
=
$tmpArr
[
COLUMN
];
$posRow
=
$tmpArr
[
ROW
];
$arr
=
explode
(
PHP_EOL
,
$data
);
foreach
(
$arr
as
$line
)
{
$line
=
trim
(
$line
);
// Skip empty /comment lines
if
(
empty
(
$line
)
||
$line
[
0
]
==
TOKEN_COMMENT
)
{
continue
;
}
$token
=
explode
(
':'
,
$line
,
2
);
switch
(
$token
[
0
])
{
case
EXCEL_WORKSHEET
:
throw
new
downloadException
(
"Not implemented: "
.
$token
[
0
],
ERROR_NOT_IMPLEMENTED
);
case
EXCEL_MODE
:
throw
new
downloadException
(
"Not implemented: "
.
$token
[
0
],
ERROR_NOT_IMPLEMENTED
);
case
EXCEL_POSITION
:
if
(
empty
(
$token
[
1
]))
{
throw
new
downloadException
(
"Position argument is empty"
,
ERROR_EXCEL_POSITION_ARGUMENT_EMPTY
);
}
$pos
=
$token
[
1
];
$tmpArr
=
OnString
::
splitExcelPos
(
$pos
);
$posColumn
=
$tmpArr
[
COLUMN
];
$posRow
=
$tmpArr
[
ROW
];
break
;
case
EXCEL_ROW
:
$posRow
++
;
break
;
case
EXCEL_STRING
:
$worksheet
->
setCellValue
(
$posColumn
.
$posRow
,
$token
[
1
]);
$posColumn
=
$this
->
nextColumn
(
$posColumn
);
break
;
case
EXCEL_NUMBER
:
case
EXCEL_CURRENCY
:
case
EXCEL_DATE
:
case
EXCEL_DATETIME
:
case
EXCEL_TIME
:
throw
new
downloadException
(
"Not implemented: "
.
$token
[
0
],
ERROR_NOT_IMPLEMENTED
);
}
}
return
$spreadsheet
;
}
/**
* Increment the alpha string. If 'Z' is reached on the last position, it appends 'A'.
* 'A' > 'B'
* 'Z' > 'ZA'
* 'ZA' > 'ZB'
*
* @param $column
* @return string - incremented column.
*/
private
function
nextColumn
(
$column
)
{
$len
=
strlen
(
$column
);
$c
=
$column
[
$len
-
1
];
if
(
$c
==
'Z'
)
{
$column
.
=
'A'
;
}
else
{
$c
=
++
$c
;
$column
[
$len
-
1
]
=
$c
;
}
return
$column
;
}
}
\ No newline at end of file
extension/qfq/qfq/report/Html2Pdf.php
View file @
b6cfd023
...
...
@@ -93,7 +93,7 @@ class Html2Pdf {
private
function
readCleanGetParam
(
array
$get
)
{
$param
=
array
();
$pattern
=
'^[\-_\.,;:\/a-zA-Z0-9]*$'
;
// ':alnum:' does not work here in FF
$pattern
=
'^[\-_\.,;:\/a-zA-Z0-9]*$'
;
foreach
(
$get
as
$key
=>
$value
)
{
if
(
preg_match
(
"/
$pattern
/"
,
$value
)
===
1
)
{
...
...
@@ -178,7 +178,7 @@ class Html2Pdf {
break
;
case
TOKEN_URL_PARAM
:
case
TOKEN_PAGE
:
$host
=
$this
->
config
[
SYSTEM_BASE_URL
];
$host
=
$this
->
config
[
SYSTEM_BASE_URL
];
$urlParamString
=
$url
;
break
;
default
:
...
...
@@ -207,7 +207,7 @@ class Html2Pdf {
$urlPrint
=
escapeshellarg
(
$url
);
$wkhtmlToPdf
=
$this
->
config
[
SYSTEM_CMD_WKHTMLTOPDF
];
$filename
=
tempnam
(
sys_get_temp_dir
(),
TMP_FILE_PREFIX
);
$filename
=
HelperFile
::
tempnam
(
);
$filenameEscape
=
escapeshellarg
(
$filename
);
$cookieOptions
=
'--cookie-jar '
.
escapeshellarg
(
$this
->
sessionCookie
->
getFile
());
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment