When merging into a spreadsheet document, convert dates into SS dates

This commit is contained in:
Nathan Gray 2012-02-13 18:59:00 +00:00
parent 59b277ec5f
commit 4f669300a4
2 changed files with 113 additions and 31 deletions

View File

@ -29,6 +29,11 @@ abstract class bo_merge
*/
var $datetime_format = 'Y-m-d H:i';
/**
* Fields that are to be treated as datetimes, when merged into spreadsheets
*/
var $date_fields = array();
/**
* Mimetype of document processed by merge
*
@ -903,43 +908,24 @@ abstract class bo_merge
}
// Look for numbers, set their value if needed
$format = $replacement = '';
if($this->numeric_fields || count($names))
{
foreach((array)$this->numeric_fields as $fieldname) {
$names[] = preg_quote($fieldname,'/');
}
switch($mimetype.$mso_application_progid)
{
case 'application/vnd.oasis.opendocument.spreadsheet': // open office calc
$format = '/<table:table-cell([^>]+?)office:value-type="[^"]+"([^>]*?)>.?<([a-z].*?)[^>]*>('.implode('|',$names).')<\/\3>.?<\/table:table-cell>/s';
$replacement = '<table:table-cell$1office:value-type="float" office:value="$4"$2>$4</table:table-cell>';
break;
case 'application/xmlExcel.Sheet': // Excel 2003
$format = '/'.preg_quote('<Data ss:Type="String">','/').'('.implode('|',$names).')'.preg_quote('</Data>','/').'/';
$replacement = '<Data ss:Type="Number">$1</Data>';
$this->format_spreadsheet_numbers($content, $names, $mimetype.$mso_application_progid);
}
break;
}
if($format && $names)
// Look for dates, set their value if needed
if($this->date_fields || count($names))
{
// Dealing with backtrack limit per AmigoJack 10-Jul-2010 comment on php.net preg-replace docs
$increase = 0;
while($increase < 10) {
$result = preg_replace($format, $replacement, $content, -1, $count);
if( preg_last_error()== PREG_BACKTRACK_LIMIT_ERROR ) { // Only check on backtrack limit failure
ini_set( 'pcre.backtrack_limit', (int)ini_get( 'pcre.backtrack_limit' )+ 10000 ); // Get current limit and increase
$increase++; // Do not overkill the server
} else { // No fail
$content = $result; // On failure $result would be NULL
break; // Exit loop
}
}
if($increase == 10) {
error_log('Backtrack limit exceeded @ ' . ini_get('pcre.backtrack_limit') . ', some cells left as text.');
}
$names = array();
foreach((array)$this->date_fields as $fieldname) {
$names[] = preg_quote($fieldname,'/');
}
$this->format_spreadsheet_dates($content, $names, $replacements, $mimetype.$mso_application_progid);
}
// replace CRLF with linebreak tag of given type
switch($mimetype.$mso_application_progid)
{
@ -973,6 +959,94 @@ abstract class bo_merge
return str_replace(array_keys($replacements),array_values($replacements),$content);
}
/**
* Convert numeric values in spreadsheets into actual numeric values
*/
protected function format_spreadsheet_numbers(&$content, $names, $mimetype)
{
foreach((array)$this->numeric_fields as $fieldname) {
$names[] = preg_quote($fieldname,'/');
}
switch($mimetype)
{
case 'application/vnd.oasis.opendocument.spreadsheet': // open office calc
$format = '/<table:table-cell([^>]+?)office:value-type="[^"]+"([^>]*?)>.?<([a-z].*?)[^>]*>('.implode('|',$names).')<\/\3>.?<\/table:table-cell>/s';
$replacement = '<table:table-cell$1office:value-type="float" office:value="$4"$2>$4</table:table-cell>';
break;
case 'application/xmlExcel.Sheet': // Excel 2003
$format = '/'.preg_quote('<Data ss:Type="String">','/').'('.implode('|',$names).')'.preg_quote('</Data>','/').'/';
$replacement = '<Data ss:Type="Number">$1</Data>';
break;
}
if($format && $names)
{
// Dealing with backtrack limit per AmigoJack 10-Jul-2010 comment on php.net preg-replace docs
$increase = 0;
while($increase < 10) {
$result = preg_replace($format, $replacement, $content, -1, $count);
if( preg_last_error()== PREG_BACKTRACK_LIMIT_ERROR ) { // Only check on backtrack limit failure
ini_set( 'pcre.backtrack_limit', (int)ini_get( 'pcre.backtrack_limit' )+ 10000 ); // Get current limit and increase
$increase++; // Do not overkill the server
} else { // No fail
$content = $result; // On failure $result would be NULL
break; // Exit loop
}
}
if($increase == 10) {
error_log('Backtrack limit exceeded @ ' . ini_get('pcre.backtrack_limit') . ', some cells left as text.');
}
}
}
/**
* Convert date / timestamp values in spreadsheets into actual date / timestamp values
*/
protected function format_spreadsheet_dates(&$content, $names, &$values, $mimetype)
{
switch($mimetype)
{
case 'application/vnd.oasis.opendocument.spreadsheet': // open office calc
$format = '/<table:table-cell([^>]+?)office:value-type="[^"]+"([^>]*?)>.?<([a-z].*?)[^>]*>..('.implode('|',$names).')..<\/\3>.?<\/table:table-cell>/s';
$replacement = '<table:table-cell$1office:value-type="date" office:date-value="\$\$$4\$\$"$2><$3>\$\$$4\$\$</$3></table:table-cell>';
break;
case 'application/xmlExcel.Sheet': // Excel 2003
$format = '/'.preg_quote('<Data ss:Type="String">','/').'..('.implode('|',$names).')..'.preg_quote('</Data>','/').'/';
$replacement = '<Data ss:Type="Number">\$\$$1\$\$</Data>';
break;
}
if($format && $names)
{
// Dealing with backtrack limit per AmigoJack 10-Jul-2010 comment on php.net preg-replace docs
$increase = 0;
while($increase < 10) {
$result = preg_replace($format, $replacement, $content, -1, $count);
if( preg_last_error()== PREG_BACKTRACK_LIMIT_ERROR ) { // Only check on backtrack limit failure
ini_set( 'pcre.backtrack_limit', (int)ini_get( 'pcre.backtrack_limit' )+ 10000 ); // Get current limit and increase
$increase++; // Do not overkill the server
} else { // No fail
$content = $result; // On failure $result would be NULL
break; // Exit loop
}
}
if($increase == 10) {
error_log('Backtrack limit exceeded @ ' . ini_get('pcre.backtrack_limit') . ', some cells left as text.');
}
}
// Properly format values for spreadsheet
foreach($names as $field)
{
$key = '$$'.$field.'$$';
if($values[$key])
{
$date = egw_time::createFromFormat($this->datetime_format,$values[$key]);
$values[$key] = date('Y-m-d\TH:i:s',egw_time::to($date,'ts'));
}
}
}
/**
* Process special flags, such as IF or NELF
*

View File

@ -39,6 +39,14 @@ class infolog_merge extends bo_merge
{
parent::__construct();
$this->bo = new infolog_bo();
$this->date_fields += array(
'info_startdate',
'info_enddate',
'info_datecompleted',
'info_datemodified',
'info_created',
);
}
/**