Support of date and time custom formats... continuing towards the beta !

SVN:trunk[4019]
This commit is contained in:
Denis Flaven
2016-05-03 09:56:02 +00:00
parent 7d4e9ce069
commit 5386662146
32 changed files with 518 additions and 460 deletions

View File

@@ -34,6 +34,7 @@ require_once('htmlsanitizer.class.inc.php');
require_once(APPROOT.'sources/autoload.php');
require_once('customfieldshandler.class.inc.php');
require_once('ormcustomfieldsvalue.class.inc.php');
require_once('datetimeformat.class.inc.php');
// This should be changed to a use when we go full-namespace
require_once(APPROOT . 'sources/form/validator/validator.class.inc.php');
require_once(APPROOT . 'sources/form/validator/notemptyextkeyvalidator.class.inc.php');
@@ -298,6 +299,15 @@ abstract class AttributeDefinition
return $this->MakeRealValue($sProposedValue, null);
}
/**
* Parses a search string coming from user input
* @param string $sSearchString
* @return string
*/
public function ParseSearchString($sSearchString)
{
return $sSearchString;
}
public function GetLabel_Obsolete()
{
// Written for compatibility with a data model written prior to version 0.9.1
@@ -3537,17 +3547,16 @@ class AttributeMetaEnum extends AttributeEnum
*/
class AttributeDateTime extends AttributeDBField
{
static $sDateTimeFormat = null;
static $sTimeFormat = null;
static $oFormat = null;
static public function GetFormat()
{
if (self::$sDateTimeFormat == null)
if (self::$oFormat == null)
{
static::LoadFormatFromConfig();
}
return self::$sDateTimeFormat;
}
return self::$oFormat;
}
/**
* Load the 3 settings: date format, time format and data_time format from the configuration
@@ -3560,11 +3569,10 @@ class AttributeDateTime extends AttributeDBField
$sTimeFormat = isset($aFormats[$sLang]['time']) ? $aFormats[$sLang]['time'] : (isset($aFormats['default']['time']) ? $aFormats['default']['time'] : 'H:i:s');
$sDateAndTimeFormat = isset($aFormats[$sLang]['date_time']) ? $aFormats[$sLang]['date_time'] : (isset($aFormats['default']['date_time']) ? $aFormats['default']['date_time'] : '$date $time');
$sFormat = str_replace(array('$date', '$time'), array($sDateFormat, $sTimeFormat), $sDateAndTimeFormat);
$sFullFormat = str_replace(array('$date', '$time'), array($sDateFormat, $sTimeFormat), $sDateAndTimeFormat);
self::SetFormat($sFormat);
self::SetTimeFormat($sTimeFormat);
AttributeDate::SetFormat($sDateFormat);
self::SetFormat(new DateTimeFormat($sFullFormat));
AttributeDate::SetFormat(new DateTimeFormat($sDateFormat));
}
/**
@@ -3585,18 +3593,9 @@ class AttributeDateTime extends AttributeDBField
return 'Y-m-d H:i:s';
}
static public function SetFormat($sDateTimeFormat)
static public function SetFormat(DateTimeFormat $oDateTimeFormat)
{
self::$sDateTimeFormat = $sDateTimeFormat;
}
static public function GetTimeFormat()
{
if (self::$sTimeFormat == null)
{
static::LoadFormatFromConfig();
}
return self::$sTimeFormat;
self::$oFormat = $oDateTimeFormat;
}
static public function GetSQLTimeFormat()
@@ -3604,286 +3603,47 @@ class AttributeDateTime extends AttributeDBField
return 'H:i:s';
}
static public function SetTimeFormat($sTimeFormat)
{
self::$sTimeFormat = $sTimeFormat;
}
/**
* Return the mapping table for converting between various convention for data formats
*/
public static function GetFormatMapping()
{
return array(
// Days
'd' => array('regexpr' => '(0[1-9]|[1-2][0-9]||3[0-1])', 'datepicker' => 'dd', 'usage' => 'day', 'excel' => 'dd'), // Day of the month: 2 digits (with leading zero)
'j' => array('regexpr' => '([1-9]|[1-2][0-9]||3[0-1])', 'datepicker' => 'd', 'usage' => 'day', 'excel' => '%d'), // Day of the month: 1 or 2 digits (without leading zero)
// Months
'm' => array('regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'mm', 'usage' => 'month', 'excel' => 'MM'), // Month on 2 digits i.e. 01-12
'n' => array('regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'm', 'usage' => 'month', 'excel' => '%M'), // Month on 1 or 2 digits 1-12
// Years
'Y' => array('regexpr' => '([0-9]{4})', 'datepicker' => 'yy', 'usage' => 'year', 'excel' => 'YYYY'), // Year on 4 digits
'y' => array('regexpr' => '([0-9]{2})', 'datepicker' => 'y', 'usage' => 'year', 'excel' => 'YY'), // Year on 2 digits
// Hours
'H' => array('regexpr' => '([0-1][0-9]|2[0-3])', 'datepicker' => 'HH', 'usage' => 'hour', 'excel' => 'HH'), // Hour 00..23
'h' => array('regexpr' => '(0[1-9]|1[0-2])', 'datepicker' => 'hh', 'usage' => 'hour', 'excel' => 'hh'), // Hour 01..12
'G' => array('regexpr' => '([1-9]|[1[0-9]|2[0-3])', 'datepicker' => 'H', 'usage' => 'hour', 'excel' => '%H'), // Hour 0..23
'g' => array('regexpr' => '([1-9]|1[0-2])', 'datepicker' => 'h', 'usage' => 'hour', 'excel' => '%h'), // Hour 1..12
'a' => array('regexpr' => '(am|pm)', 'datepicker' => 'tt', 'usage' => 'am/pm', 'excel' => 'am/pm'),
'A' => array('regexpr' => '(AM|PM)', 'datepicker' => 'TT', 'usage' => 'am/pm', 'excel' => 'AM/PM'),
// Minutes
'i' => array('regexpr' => '([0-5][0-9])', 'datepicker' => 'mm', 'usage' => 'minutes', 'excel' => 'mm'),
// Seconds
's' => array('regexpr' => '([0-5][0-9])', 'datepicker' => 'ss', 'usage' => 'seconds', 'excel' => 'ss'),
);
}
/**
* Format a date into the supplied format string
* @param mixed $date An int, string, DateTime object or null !!
* @param string $sFormat The format using PHP createFromFormat convention
* @throws Exception
* @return string The formatted date
*/
public static function Format($date, $sFormat = null)
{
if ($sFormat === null)
{
$sFormat = static::GetFormat();
}
if ($date == null)
{
$sDate = '';
}
else if (($date === '0000-00-00') || ($date === '0000-00-00 00:00:00'))
{
$sDate = '';
}
else if ($date instanceof DateTime)
{
// Parameter is a DateTime
$sDate = $date->format($sFormat);
}
else if (is_int($date))
{
// Parameter is a Unix timestamp
$oDate = new DateTime();
$oDate->setTimestamp($date);
$sDate = $oDate->format($sFormat);
}
else if (is_string($date))
{
$oDate = new DateTime($date);
$sDate = $oDate->format($sFormat);
}
else
{
throw new Exception("AttributeDateTime::Format: Unexpected date value: ".print_r($date, true));
}
return $sDate;
}
/**
* Parse a date in the supplied format and return the date as a string in the internal format
* @param string $sDate The string to parse
* @param string $sFormat The format, in PHP createFromFormat convention
* @throws Exception
* Parses a search string coming from user input
* @param string $sSearchString
* @return string
*/
public static function Parse($sDate, $sFormat)
public function ParseSearchString($sSearchString)
{
if (($sDate == null) || ($sDate == '0000-00-00 00:00:00') || ($sDate == '0000-00-00'))
try
{
return null;
$oDateTime = $this->GetFormat()->Parse($sSearchString);
$sSearchString = $oDateTime->format($this->GetInternalFormat());
}
else
catch(Exception $e)
{
$sFormat = preg_replace('/\\?/', '', $sFormat); // replace escaped characters by a wildcard for parsing
$oDate = DateTime::createFromFormat($sFormat, $sDate);
if ($oDate === false)
$sFormatString = '!'.(string)AttributeDate::GetFormat(); // BEWARE: ! is needed to set non-parsed fields to zero !!!
$oDateTime = DateTime::createFromFormat($sFormatString, $sSearchString);
if ($oDateTime !== false)
{
throw new Exception("Unable to parse the date: '$sDate' using the format: '$sFormat'");
$sSearchString = $oDateTime->format($this->GetInternalFormat());
}
return $oDate->format(static::GetInternalFormat());
}
return $sSearchString;
}
static public function GetFormFieldClass()
{
return '\\Combodo\\iTop\\Form\\Field\\DateTimeField';
}
/**
* Get a date or datetime format string in the jQuery UI date picker format
* @param string $sFormat
* @return string The format string using the date picker convention
* Override to specify Field class
*
* When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the $oFormField is passed, MakeFormField behave more like a Prepare.
*/
static public function GetDatePickerFormat()
public function MakeFormField(DBObject $oObject, $oFormField = null)
{
$sFormat = static::GetFormat();
$aMappings = static::GetFormatMapping();
$sResult = '';
$oFormField = parent::MakeFormField($oObject, $oFormField);
$oFormField->SetPHPDateTimeFormat($this->GetFormat());
$oFormField->SetJSDateTimeFormat($this->GetMomentJSFormat());
$bEscaping = false;
for($i=0; $i < strlen($sFormat); $i++)
{
if (($sFormat[$i] == '\\'))
{
$bEscaping = true;
continue;
}
if ($bEscaping)
{
$sResult .= "'{$sFormat[$i]}'";
$bEscaping = false;
}
else if(array_key_exists($sFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by its regular expression pattern
$sResult .= $aMappings[$sFormat[$i]]['datepicker'];
}
else
{
// Normal char with no special meaning
$sResult .= $sFormat[$i];
}
}
return $sResult;
}
/**
* Get a date or datetime format string in the Excel format
* @param string $sFormat
* @return string The format string using the Excel convention
*/
static public function GetExcelFormat($sFormat = null)
{
$sFormat = ($sFormat == null) ? static::GetFormat() : $sFormat;
$aMappings = static::GetFormatMapping();
$sResult = '';
$bEscaping = false;
for($i=0; $i < strlen($sFormat); $i++)
{
if (($sFormat[$i] == '\\'))
{
$bEscaping = true;
continue;
}
if ($bEscaping)
{
$sResult .= $sFormat[$i]; // What's the way to escape characters in Excel format ??
$bEscaping = false;
}
else if(array_key_exists($sFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by its regular expression pattern
$sResult .= $aMappings[$sFormat[$i]]['excel'];
}
else
{
// Normal char with no special meaning
$sResult .= $sFormat[$i];
}
}
return $sResult;
}
/*
* Unused since the sorting of the tables is always performed server-side
*
public static function GetTableSorterRule()
{
$aOrder = array();
$aPos = array();
$sRegExpr = static::GetRegExpr($aOrder);
foreach(array('year', 'month', 'day', 'hour', 'minutes', 'seconds') as $sUsage)
{
$pos = array_search($sUsage, $aOrder);
if ($pos !== false)
{
$aPos[$sUsage] = '$'.(1+$pos);
}
}
$sIsoDate = "{$aPos['year']}/{$aPos['month']}/{$aPos['day']}";
if (array_key_exists('hour', $aPos))
{
$sIsoDate .= " {$aPos['hour']}:{$aPos['minutes']}:{$aPos['seconds']}";
}
return array('regexpr' => $sRegExpr, 'replacement' => $sIsoDate);
}
public static function InitTableSorter($oPage, $sRuleName)
{
$aDef = static::GetTableSorterRule();
$oPage->add_ready_script(
<<<EOF
$.tablesorter.addParser({
id: "$sRuleName",
is: function (s) {
return /^({$aDef['regexpr']})$/.test(s);
}, format: function (s) {
s = s.replace(/{$aDef['regexpr']}/, "{$aDef['replacement']}");
return $.tablesorter.formatFloat(new Date(s).getTime());
}, type: "numeric"
});
EOF
);
}
*/
/**
* Get the regular expression to (approximately) validate a date/time for the current format
* @param array $aOrder
* @return string The regular expression in PCRE syntax
*/
static public function GetRegExpr(&$aOrder = null)
{
$sFormat = static::GetFormat();
$aMappings = static::GetFormatMapping();
$sSpecialChars = '.?*$^()[]/'; // Characters having a special meaning in a regular expression, must be escaped by prepending a backslash
$sResult = '^';
$bEscaping = false;
for($i=0; $i < strlen($sFormat); $i++)
{
if (($sFormat[$i] == '\\') && !$bEscaping)
{
$bEscaping = true;
continue;
}
if (!$bEscaping && array_key_exists($sFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by its regular expression pattern
$sResult .= $aMappings[$sFormat[$i]]['regexpr'];
if ($aOrder !== null)
{
$aOrder[] = $aMappings[$sFormat[$i]]['usage'];
}
}
else
{
// Litteral value, take care of special characters in a RegExpr
if (strpos($sSpecialChars, $sFormat[$i]) !== false)
{
$sResult .= '\\'.$sFormat[$i];
}
else
{
// Normal char with no special meaning
$sResult .= $sFormat[$i];
}
}
if ($bEscaping)
{
$bEscaping = false;
}
}
$sResult .= '$';
return $sResult;
return $oFormField;
}
static public function ListExpectedParams()
@@ -3897,7 +3657,11 @@ EOF
public function GetEditValue($sValue, $oHostObj = null)
{
return (string)static::Format($sValue, static::GetFormat());
return (string)static::GetFormat()->format($sValue);
}
public function GetValueLabel($sValue, $oHostObj = null)
{
return (string)static::GetFormat()->format($sValue);
}
protected function GetSQLCol($bFullSpec = false) {return "DATETIME";}
@@ -3916,7 +3680,7 @@ EOF
public function GetValidationPattern()
{
return static::GetRegExpr();
return static::GetFormat()->ToRegExpr();
}
public function GetBasicFilterOperators()
@@ -3990,7 +3754,7 @@ EOF
return $proposedValue;
}
return date(self::GetInternalFormat(), $proposedValue);
return date(static::GetInternalFormat(), $proposedValue);
}
public function ScalarToSQL($value)
@@ -4009,7 +3773,7 @@ EOF
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
{
return Str::pure2html(static::Format($value, static::GetFormat()));
return Str::pure2html(static::GetFormat()->format($value));
}
public function GetAsXML($value, $oHostObject = null, $bLocalize = true)
@@ -4023,13 +3787,13 @@ EOF
{
return '';
}
else if (self::GetFormat() !== self::GetInternalFormat())
else if ((string)static::GetFormat() !== static::GetInternalFormat())
{
// Format conversion
$oDate = new DateTime($sValue);
if ($oDate !== false)
{
$sValue = $oDate->format(self::GetFormat());
$sValue = static::GetFormat()->format($oDate);
}
}
$sFrom = array("\r\n", $sTextQualifier);
@@ -4047,7 +3811,7 @@ EOF
* @param Hash $aParams Values of the query parameters
* @return Expression The search condition to be added (AND) to the current search
*/
public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams)
public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams, $bParseSearchString = false)
{
// Possible smart patterns
$aPatterns = array(
@@ -4075,13 +3839,27 @@ EOF
$sParamName1 = $oField->GetParent().'_'.$oField->GetName().'_1';
$oRightExpr = new VariableExpression($sParamName1);
if ($bParseSearchString)
{
$aParams[$sParamName1] = $this->ParseSearchString($aMatches[1]);
}
else
{
$aParams[$sParamName1] = $aMatches[1];
}
$oCondition1 = new BinaryExpression($oField, '>=', $oRightExpr);
$sParamName2 = $oField->GetParent().'_'.$oField->GetName().'_2';
$oRightExpr = new VariableExpression($sParamName2);
$sOperator = $this->GetBasicFilterLooseOperator();
if ($bParseSearchString)
{
$aParams[$sParamName2] = $this->ParseSearchString($aMatches[2]);
}
else
{
$aParams[$sParamName2] = $aMatches[2];
}
$oCondition2 = new BinaryExpression($oField, '<=', $oRightExpr);
$oNewCondition = new BinaryExpression($oCondition1, 'AND', $oCondition2);
@@ -4094,18 +3872,35 @@ EOF
$sSQLOperator = $aPatterns[$sPatternFound]['operator'];
$sParamName = $oField->GetParent().'_'.$oField->GetName();
$oRightExpr = new VariableExpression($sParamName);
if ($bParseSearchString)
{
$aParams[$sParamName] = $this->ParseSearchString($aMatches[1]);
}
else
{
$aParams[$sParamName] = $aMatches[1];
}
$oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr);
break;
default:
$oNewCondition = parent::GetSmartConditionExpression($sSearchText, $oField, $aParams);
$oNewCondition = parent::GetSmartConditionExpression($sSearchText, $oField, $aParams, $bParseSearchString);
}
return $oNewCondition;
}
public function GetHelpOnSmartSearch()
{
$sDict = parent::GetHelpOnSmartSearch();
$oFormat = static::GetFormat();
$sExample = $oFormat->Format(new DateTime('2015-07-19 18:40:00'));
return vsprintf($sDict, array($oFormat->ToPlaceholder(), $sExample));
}
}
/**
@@ -4188,20 +3983,20 @@ class AttributeDuration extends AttributeInteger
*/
class AttributeDate extends AttributeDateTime
{
static $sDateFormat = null;
static $oDateFormat = null;
static public function GetFormat()
{
if (self::$sDateFormat == null)
if (self::$oDateFormat == null)
{
AttributeDateTime::LoadFormatFromConfig();
}
return self::$sDateFormat;
return self::$oDateFormat;
}
static public function SetFormat($sDateFormat)
static public function SetFormat(DateTimeFormat $oDateFormat)
{
self::$sDateFormat = $sDateFormat;
self::$oDateFormat = $oDateFormat;
}
/**
@@ -4251,7 +4046,7 @@ class AttributeDeadline extends AttributeDateTime
if ($value !== null)
{
$iValue = AttributeDateTime::GetAsUnixSeconds($value);
$sDate = $value;
$sDate = AttributeDateTime::Format($value);
$difference = $iValue - time();
if ($difference >= 0)

View File

@@ -554,7 +554,15 @@ class BulkChange
else
{
// By default... nothing happens
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oAttDef instanceof AttributeDateTime)
{
$aResults[$iCol]= new CellStatus_Void($oAttDef->GetFormat()->Format($aRowData[$iCol]));
}
else
{
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
}
}
}
}
@@ -795,6 +803,11 @@ class BulkChange
if (!is_null($this->m_sDateFormat) && (strlen($this->m_sDateFormat) > 0))
{
$sDateTimeFormat = $this->m_sDateFormat; // the specified format is actually the date AND time format
$oDateTimeFormat = new DateTimeFormat($sDateTimeFormat);
$sDateFormat = $oDateTimeFormat->ToDateFormat();
AttributeDateTime::SetFormat($oDateTimeFormat);
AttributeDate::SetFormat(new DateTimeFormat($sDateFormat));
// Translate dates from the source data
//
foreach ($this->m_aAttList as $sAttCode => $iCol)
@@ -802,21 +815,34 @@ class BulkChange
if ($sAttCode == 'id') continue;
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oAttDef instanceof AttributeDateTime)
if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
{
foreach($this->m_aData as $iRow => $aRowData)
{
$oDate = DateTime::createFromFormat($this->m_sDateFormat, $this->m_aData[$iRow][$iCol]);
if ($oDate !== false)
$sFormat = $sDateTimeFormat;
$sValue = $this->m_aData[$iRow][$iCol];
if (!empty($sValue))
{
$sNewDate = $oDate->format($oAttDef->GetInternalFormat());
$this->m_aData[$iRow][$iCol] = $sNewDate;
if ($oAttDef instanceof AttributeDate)
{
$sFormat = $sDateFormat;
}
$oDate = DateTime::createFromFormat($sFormat, $this->m_aData[$iRow][$iCol]);
if ($oDate !== false)
{
$sNewDate = $oDate->format($oAttDef->GetInternalFormat());
$this->m_aData[$iRow][$iCol] = $sNewDate;
}
else
{
// Leave the cell unchanged
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, $this->m_aData[$iRow][$iCol], Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
}
}
else
{
// Leave the cell unchanged
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, $this->m_aData[$iRow][$iCol], Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$this->m_aData[$iRow][$iCol] = '';
}
}
}

View File

@@ -34,7 +34,7 @@ class CSVBulkExport extends TabularBulkExport
$oP->p(" *\ttext-qualifier: (optional) character to be used around text strings (default is '\"').");
$oP->p(" *\tno_localize: set to 1 to retrieve non-localized values (for instance for ENUM values). Default is 0 (= localized values)");
$oP->p(" *\tformatted_text: set to 1 to export case logs and formatted text fields with their HTML markup. Default is 0 (= plain text)");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the format used in the user interface). Example: 'm/d/Y H:i:s'");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the SQL format used in the user interface). e.g. 'Y-m-d H:i:s'");
}
public function ReadParameters()
@@ -59,14 +59,22 @@ class CSVBulkExport extends TabularBulkExport
$this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('charset', 'UTF-8', true, 'raw_data'));
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
$sDateFormatRadio = utils::ReadParam('date_format_radio', 'custom');
if ($sDateFormatRadio == 'default')
$sDateFormatRadio = utils::ReadParam('date_format_radio', '');
switch($sDateFormatRadio)
{
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
}
else
{
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
case 'default':
// Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
break;
case 'custom':
// Custom format specified from the UI
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
break;
default:
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
}
}
@@ -176,12 +184,12 @@ class CSVBulkExport extends TabularBulkExport
$oP->add('<input type="checkbox" id="csv_formatted_text" name="formatted_text" value="1"'.$sChecked.'><label for="csv_formatted_text"> '.Dict::S('Core:BulkExport:OptionFormattedText').'</label>');
$oP->add('</td><td style="vertical-align:top">');
$sDateTimeFormat = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== AttributeDateTime::GetFormat()) ? ' checked' : '';
$sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$oP->add('<h3>'.Dict::S('Core:BulkExport:DateTimeFormat').'</h3>');
$sDefaultFormat = htmlentities(AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date(AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$oP->add('<input type="radio" id="csv_date_time_format_default" name="date_format_radio" value="default"'.$sDefaultChecked.'><label for="csv_date_time_format_default"> '.Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample).'</label><br/>');
$sFormatInput = '<input type="text" size="15" name="date_format" id="csv_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oP->add('<input type="radio" id="csv_date_time_format_custom" name="date_format_radio" value="custom"'.$sCustomChecked.'><label for="csv_date_time_format_custom"> '.Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput).'</label>');
@@ -267,6 +275,17 @@ EOF
$sData = '';
$iPreviousTimeLimit = ini_get('max_execution_time');
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
$sExportDateTimeFormat = $this->aStatusInfo['date_format'];
$oPrevDateTimeFormat = AttributeDateTime::GetFormat();
$oPrevDateFormat = AttributeDate::GetFormat();
if ($sExportDateTimeFormat !== (string)$oPrevDateTimeFormat)
{
// Change date & time formats
$oDateTimeFormat = new DateTimeFormat($sExportDateTimeFormat);
$oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat());
AttributeDateTime::SetFormat($oDateTimeFormat);
AttributeDate::SetFormat($oDateFormat);
}
while($aRow = $oSet->FetchAssoc())
{
set_time_limit($iLoopTimeLimit);
@@ -287,10 +306,7 @@ EOF
break;
default:
$sPrevFormat = AttributeDateTime::GetFormat();
AttributeDateTime::SetFormat($this->aStatusInfo['date_format']);
$sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']);
AttributeDateTime::SetFormat($sPrevFormat);
}
}
if ($this->aStatusInfo['charset'] != 'UTF-8')
@@ -307,6 +323,9 @@ EOF
$sData .= implode($this->aStatusInfo['separator'], $aData)."\n";
$iCount++;
}
// Restore original date & time formats
AttributeDateTime::SetFormat($oPrevDateTimeFormat);
AttributeDate::SetFormat($oPrevDateFormat);
set_time_limit($iPreviousTimeLimit);
$this->aStatusInfo['position'] += $this->iChunkSize;
if ($this->aStatusInfo['total'] == 0)

View File

@@ -40,7 +40,15 @@ class DateTimeFormat
*/
public function __construct($sPHPFormat)
{
$this->sPHPFormat = $sPHPFormat;
$this->sPHPFormat = (string)$sPHPFormat;
}
/**
* @return string
*/
public function __toString()
{
return $this->sPHPFormat;
}
/**
@@ -231,14 +239,13 @@ class DateTimeFormat
*/
public function ToPlaceholder($sFormat = null)
{
$sFormat = ($sFormat == null) ? static::GetFormat() : $sFormat;
$aMappings = static::GetFormatMapping();
$sResult = '';
$bEscaping = false;
for($i=0; $i < strlen($sFormat); $i++)
for($i=0; $i < strlen($this->sPHPFormat); $i++)
{
if (($sFormat[$i] == '\\'))
if (($this->sPHPFormat[$i] == '\\'))
{
$bEscaping = true;
continue;
@@ -246,41 +253,41 @@ class DateTimeFormat
if ($bEscaping)
{
$sResult .= $sFormat[$i]; // No need to escape characters in the placeholder
$sResult .= $this->sPHPFormat[$i]; // No need to escape characters in the placeholder
$bEscaping = false;
}
else if(array_key_exists($sFormat[$i], $aMappings))
else if(array_key_exists($this->sPHPFormat[$i], $aMappings))
{
// Not a litteral value, must be replaced by Dict equivalent
$sResult .= Dict::S('Core:DateTime:Placeholder_'.$sFormat[$i]);
$sResult .= Dict::S('Core:DateTime:Placeholder_'.$this->sPHPFormat[$i]);
}
else
{
// Normal char with no special meaning
$sResult .= $sFormat[$i];
$sResult .= $this->sPHPFormat[$i];
}
}
return $sResult;
}
/**
* Produces the Date format string by extracting only the date part of the date and time format string
* Produces a subformat (Date or Time) by extracting the part of the whole DateTime format containing only the given placeholders
* @return string
*/
public function ToDateFormat()
protected function ToSubFormat($aPlaceholders)
{
$aDatePlaceholders = array('Y', 'y', 'd', 'j', 'm', 'n');
$iStart = 999;
$iEnd = 0;
foreach($aDatePlaceholders as $sChar)
foreach($aPlaceholders as $sChar)
{
$iPos = strpos($this->sPHPFormat, $sChar);
if ($iPos !== false)
{
if (($iPos > 0) && ($aDatePlaceholders[$iPos-1] == '\\'))
if (($iPos > 0) && ($this->sPHPFormat[$iPos-1] == '\\'))
{
// The placeholder is actually escaped, it's a litteral character, ignore it
continue;
@@ -293,6 +300,24 @@ class DateTimeFormat
return $sFormat;
}
/**
* Produces the Date format string by extracting only the date part of the date and time format string
* @return string
*/
public function ToDateFormat()
{
return $this->ToSubFormat(array('Y', 'y', 'd', 'j', 'm', 'n'));
}
/**
* Produces the Time format string by extracting only the time part of the date and time format string
* @return string
*/
public function ToTimeFormat()
{
return $this->ToSubFormat(array('H', 'h', 'G', 'g', 'i', 's'));
}
/**
* Get the regular expression to (approximately) validate a date/time for the current format
* The validation does not take into account the number of days in a month (i.e. June 31st will pass, as well as Feb 30th!)

View File

@@ -268,7 +268,7 @@ class DBObjectSearch extends DBSearch
$this->AddConditionExpression($oNewCondition);
}
public function AddCondition($sFilterCode, $value, $sOpCode = null)
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSeachString = false)
{
MyHelpers::CheckKeyInArray('filter code in class: '.$this->GetClass(), $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass()));
$oFilterDef = MetaModel::GetClassFilterDef($this->GetClass(), $sFilterCode);
@@ -283,12 +283,18 @@ class DBObjectSearch extends DBSearch
else
{
$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
$oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams);
$oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams, $bParseSeachString);
$this->AddConditionExpression($oNewCondition);
return;
}
}
MyHelpers::CheckKeyInArray('operator', $sOpCode, $oFilterDef->GetOperators());
// Parse search strings if needed and if the filter code corresponds to a valid attcode
if($bParseSeachString && MetaModel::IsValidAttCode($this->GetClass(), $sFilterCode))
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
$value = $oAttDef->ParseSearchString($value);
}
// Preserve backward compatibility - quick n'dirty way to change that API semantic
//

View File

@@ -47,7 +47,7 @@ class ExcelBulkExport extends TabularBulkExport
$oP->p(" * xlsx format options:");
$oP->p(" *\tfields: the comma separated list of field codes to export (e.g: name,org_id,service_name...).");
$oP->p(" *\tformatted_text: set to 1 to export case logs and formatted text fields with their HTML markup. Default is 0 (= plain text)");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the format used in the user interface). Example: 'm/d/Y H:i:s'");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the SQL format). e.g. 'Y-m-d H:i:s'");
}
public function ReadParameters()
@@ -55,14 +55,22 @@ class ExcelBulkExport extends TabularBulkExport
parent::ReadParameters();
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
$sDateFormatRadio = utils::ReadParam('date_format_radio', 'custom');
if ($sDateFormatRadio == 'default')
$sDateFormatRadio = utils::ReadParam('date_format_radio', '');
switch($sDateFormatRadio)
{
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
}
else
{
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
case 'default':
// Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
break;
case 'custom':
// Custom format specified from the UI
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
break;
default:
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
}
}
@@ -89,12 +97,12 @@ class ExcelBulkExport extends TabularBulkExport
$oP->add('</td><td style="vertical-align:top">');
$sDateTimeFormat = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== AttributeDateTime::GetFormat()) ? ' checked' : '';
$sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$oP->add('<h3>'.Dict::S('Core:BulkExport:DateTimeFormat').'</h3>');
$sDefaultFormat = htmlentities(AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date(AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$oP->add('<input type="radio" id="excel_date_time_format_default" name="date_format_radio" value="default"'.$sDefaultChecked.'><label for="excel_date_time_format_default"> '.Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample).'</label><br/>');
$sFormatInput = '<input type="text" size="15" name="date_format" id="excel_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oP->add('<input type="radio" id="excel_date_time_format_custom" name="date_format_radio" value="custom"'.$sCustomChecked.'><label for="excel_date_time_format_custom"> '.Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput).'</label>');
@@ -304,7 +312,8 @@ EOF
$fStartExcel = microtime(true);
$writer = new XLSXWriter();
$writer->setDateTimeFormat(AttributeDateTime::GetExcelFormat($this->aStatusInfo['date_format']));
$oDateTimeFormat = new DateTimeFormat($this->aStatusInfo['date_format']);
$writer->setDateTimeFormat($oDateTimeFormat->ToExcel());
$writer->setAuthor(UserRights::GetUserFriendlyName());
$aHeaderTypes = array();
$aHeaderNames = array();

View File

@@ -234,14 +234,14 @@ class ormCaseLog {
if (is_int($aIndex[$index]['date']))
{
// Unix timestamp
$sDate = date(AttributeDateTime::GetFormat(), $aIndex[$index]['date']);
$sDate = date((string)AttributeDateTime::GetFormat(), $aIndex[$index]['date']);
}
elseif (is_object($aIndex[$index]['date']))
{
if (version_compare(phpversion(), '5.3.0', '>='))
{
// DateTime
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
$sDate = $aIndex[$index]['date']->format((string)AttributeDateTime::GetFormat());
}
else
{
@@ -322,14 +322,14 @@ class ormCaseLog {
if (is_int($aIndex[$index]['date']))
{
// Unix timestamp
$sDate = date(AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
$sDate = date((string)AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
}
elseif (is_object($aIndex[$index]['date']))
{
if (version_compare(phpversion(), '5.3.0', '>='))
{
// DateTime
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
$sDate = $aIndex[$index]['date']->format((string)AttributeDateTime::GetFormat());
}
else
{
@@ -425,14 +425,14 @@ class ormCaseLog {
if (is_int($aIndex[$index]['date']))
{
// Unix timestamp
$sDate = date(AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
$sDate = date((string)AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
}
elseif (is_object($aIndex[$index]['date']))
{
if (version_compare(phpversion(), '5.3.0', '>='))
{
// DateTime
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
$sDate = $aIndex[$index]['date']->format((string)AttributeDateTime::GetFormat());
}
else
{

View File

@@ -31,7 +31,7 @@ class PDFBulkExport extends HTMLBulkExport
$oP->p(" *\tfields: (mandatory) the comma separated list of field codes to export (e.g: name,org_id,service_name...).");
$oP->p(" *\tpage_size: (optional) size of the page. One of A4, A3, Letter (default is 'A4').");
$oP->p(" *\tpage_orientation: (optional) the orientation of the page. Either Portrait or Landscape (default is 'Portrait').");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the format used in the user interface). Example: 'm/d/Y H:i:s'");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the SQL format). e.g. 'Y-m-d H:i:s'");
}
public function EnumFormParts()
@@ -59,12 +59,12 @@ class PDFBulkExport extends HTMLBulkExport
$oP->add('</td><td style="vertical-align:top">');
$sDateTimeFormat = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== AttributeDateTime::GetFormat()) ? ' checked' : '';
$sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$oP->add('<h3>'.Dict::S('Core:BulkExport:DateTimeFormat').'</h3>');
$sDefaultFormat = htmlentities(AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date(AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$oP->add('<input type="radio" id="pdf_date_time_format_default" name="date_format_radio" value="default"'.$sDefaultChecked.'><label for="pdf_date_time_format_default"> '.Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample).'</label><br/>');
$sFormatInput = '<input type="text" size="15" name="date_format" id="pdf_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oP->add('<input type="radio" id="pdf_date_time_format_custom" name="date_format_radio" value="custom"'.$sCustomChecked.'><label for="pdf_date_time_format_custom"> '.Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput).'</label>');
@@ -114,14 +114,22 @@ EOF
$this->aStatusInfo['page_size'] = utils::ReadParam('page_size', 'A4', true, 'raw_data');
$this->aStatusInfo['page_orientation'] = utils::ReadParam('page_orientation', 'L', true);
$sDateFormatRadio = utils::ReadParam('date_format_radio', 'custom');
if ($sDateFormatRadio == 'default')
$sDateFormatRadio = utils::ReadParam('date_format_radio', '');
switch($sDateFormatRadio)
{
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
}
else
{
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
case 'default':
// Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
break;
case 'custom':
// Custom format specified from the UI
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
break;
default:
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
}
}
@@ -141,10 +149,10 @@ EOF
public function GetNextChunk(&$aStatus)
{
$sPrevFormat = AttributeDateTime::GetFormat();
AttributeDateTime::SetFormat($this->aStatusInfo['date_format']);
$oPrevFormat = AttributeDateTime::GetFormat();
AttributeDateTime::SetFormat(new DateTimeFormat($this->aStatusInfo['date_format']));
$sData = parent::GetNextChunk($aStatus);
AttributeDateTime::SetFormat($sPrevFormat);
AttributeDateTime::SetFormat($oPrevFormat);
$hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab');
if ($hFile === false)
{

View File

@@ -30,6 +30,7 @@ class SpreadsheetBulkExport extends TabularBulkExport
$oP->p(" * spreadsheet format options:");
$oP->p(" *\tfields: (mandatory) the comma separated list of field codes to export (e.g: name,org_id,service_name...).");
$oP->p(" *\tno_localize: (optional) pass 1 to retrieve the raw (untranslated) values for enumerated fields. Default: 0.");
$oP->p(" *\tdate_format: the format to use when exporting date and time fields (default = the SQL format). e.g. 'Y-m-d H:i:s'");
}
public function EnumFormParts()
@@ -51,15 +52,59 @@ class SpreadsheetBulkExport extends TabularBulkExport
$oP->add('<table>');
$oP->add('<tr>');
$oP->add('<td><input type="checkbox" id="spreadsheet_no_localize" name="no_localize" value="1"'.$sChecked.'><label for="spreadsheet_no_localize"> '.Dict::S('Core:BulkExport:OptionNoLocalize').'</label></td>');
$sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
$sDefaultChecked = ($sDateTimeFormat == (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$sCustomChecked = ($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()) ? ' checked' : '';
$oP->add('<td>');
$oP->add('<h3>'.Dict::S('Core:BulkExport:DateTimeFormat').'</h3>');
$sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8');
$sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8');
$oP->add('<input type="radio" id="spreadsheet_date_time_format_default" name="date_format_radio" value="default"'.$sDefaultChecked.'><label for="spreadsheet_date_time_format_default"> '.Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample).'</label><br/>');
$sFormatInput = '<input type="text" size="15" name="date_format" id="spreadsheet_custom_date_time_format" title="" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>';
$oP->add('<input type="radio" id="spreadsheet_date_time_format_custom" name="date_format_radio" value="custom"'.$sCustomChecked.'><label for="spreadsheet_date_time_format_custom"> '.Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput).'</label>');
$oP->add('</td>');
$oP->add('</tr>');
$oP->add('</table>');
$oP->add('</fieldset>');
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
$oP->add_ready_script(
<<<EOF
$('#spreadsheet_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
$('#spreadsheet_custom_date_time_format').on('click', function() { $('#spreadsheet_date_time_format_custom').prop('checked', true); });
EOF
);
break;
default:
return parent:: DisplayFormPart($oP, $sPartId);
}
}
public function ReadParameters()
{
parent::ReadParameters();
$sDateFormatRadio = utils::ReadParam('date_format_radio', '');
switch($sDateFormatRadio)
{
case 'default':
// Export from the UI => format = same as is the UI
$this->aStatusInfo['date_format'] = (string)AttributeDateTime::GetFormat();
break;
case 'custom':
// Custom format specified from the UI
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data');
break;
default:
// Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data');
}
}
protected function GetSampleData($oObj, $sAttCode)
{
@@ -89,6 +134,10 @@ class SpreadsheetBulkExport extends TabularBulkExport
{
$sRet = $oObj->GetAsHTML($sAttCode);
}
elseif ($oAttDef instanceof AttributeCustomFields)
{
$sRet = $oObj->GetAsHTML($sAttCode);
}
else
{
if ($this->bLocalizeOutput)
@@ -97,7 +146,7 @@ class SpreadsheetBulkExport extends TabularBulkExport
}
else
{
$sRet = htmlentities($value, ENT_QUOTES, 'UTF-8');
$sRet = htmlentities((string)$value, ENT_QUOTES, 'UTF-8');
}
}
}
@@ -164,7 +213,13 @@ class SpreadsheetBulkExport extends TabularBulkExport
$oSet = new DBObjectSet($this->oSearch);
$oSet->SetLimit($this->iChunkSize, $this->aStatusInfo['position']);
$this->OptimizeColumnLoad($oSet);
$sExportDateTimeFormat = $this->aStatusInfo['date_format'];
// Date & time formats
$oDateTimeFormat = new DateTimeFormat($sExportDateTimeFormat);
$oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat());
$oTimeFormat = new DateTimeFormat($oDateTimeFormat->ToTimeFormat());
$iCount = 0;
$sData = '';
$iPreviousTimeLimit = ini_get('max_execution_time');
@@ -199,10 +254,16 @@ class SpreadsheetBulkExport extends TabularBulkExport
$oFinalAttDef = $oAttDef->GetFinalAttDef();
if (get_class($oFinalAttDef) == 'AttributeDateTime')
{
$iDate = AttributeDateTime::GetAsUnixSeconds($oObj->Get($sAttCode));
$sData .= '<td>'.date('Y-m-d', $iDate).'</td>'; // Add the first column directly
$sField = date('H:i:s', $iDate); // Will add the second column below
$sData .= "<td>$sField</td>";
// Split the date and time in two columns
$sDate = $oDateFormat->Format($oObj->Get($sAttCode));
$sTime = $oTimeFormat->Format($oObj->Get($sAttCode));
$sData .= "<td>$sDate</td>";
$sData .= "<td>$sTime</td>";
}
else if (get_class($oFinalAttDef) == 'AttributeDate')
{
$sDate = $oDateFormat->Format($oObj->Get($sAttCode));
$sData .= "<td>$sDate</td>";
}
else if($oAttDef instanceof AttributeCaseLog)
{