mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-19 08:38:45 +02:00
Enhancement: Date and time formats are now configurable in iTop !! (beta version, beware!)
SVN:trunk[4011]
This commit is contained in:
@@ -630,7 +630,6 @@ EOF
|
||||
{
|
||||
if ($iFlags & (OPT_ATT_READONLY|OPT_ATT_SLAVE))
|
||||
{
|
||||
|
||||
// Check if the attribute is not read-only because of a synchro...
|
||||
$aReasons = array();
|
||||
$sSynchroIcon = '';
|
||||
@@ -1312,8 +1311,8 @@ EOF
|
||||
else
|
||||
{
|
||||
$iDate = AttributeDateTime::GetAsUnixSeconds($sDate);
|
||||
$aRow[] = '<td>'.date('Y-m-d', $iDate).'</td>';
|
||||
$aRow[] = '<td>'.date('H:i:s', $iDate).'</td>';
|
||||
$aRow[] = '<td>'.date('Y-m-d', $iDate).'</td>'; // Format kept as-is for 100% backward compatibility of the exports
|
||||
$aRow[] = '<td>'.date('H:i:s', $iDate).'</td>'; // Format kept as-is for 100% backward compatibility of the exports
|
||||
}
|
||||
}
|
||||
else if($oAttDef instanceof AttributeCaseLog)
|
||||
@@ -1711,10 +1710,7 @@ EOF
|
||||
$aEventsList[] ='validate';
|
||||
$aEventsList[] ='keyup';
|
||||
$aEventsList[] ='change';
|
||||
if (($iFlags & OPT_ATT_MANDATORY) && (empty($sDisplayValue)))
|
||||
{
|
||||
$sDisplayValue = date($oAttDef->GetDateFormat());
|
||||
}
|
||||
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/> {$sValidationSpan}{$sReloadSpan}";
|
||||
break;
|
||||
|
||||
@@ -1722,11 +1718,8 @@ EOF
|
||||
$aEventsList[] ='validate';
|
||||
$aEventsList[] ='keyup';
|
||||
$aEventsList[] ='change';
|
||||
if (($iFlags & OPT_ATT_MANDATORY) && (empty($sDisplayValue)))
|
||||
{
|
||||
$sDisplayValue = date($oAttDef->GetDateFormat());
|
||||
}
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/> {$sValidationSpan}{$sReloadSpan}";
|
||||
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"15\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/> {$sValidationSpan}{$sReloadSpan}";
|
||||
break;
|
||||
|
||||
case 'Duration':
|
||||
@@ -3161,6 +3154,14 @@ EOF
|
||||
'to_be_added' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tba", '[]', 'raw_data'), true),
|
||||
'to_be_removed' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbr", '[]', 'raw_data'), true) );
|
||||
}
|
||||
else if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
|
||||
{
|
||||
$value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
|
||||
if ($value != null)
|
||||
{
|
||||
$value = AttributeDateTime::Parse($value, $oAttDef->GetFormat());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
|
||||
|
||||
@@ -63,6 +63,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->add_header("Cache-control: no-cache");
|
||||
$this->add_linked_stylesheet("../css/jquery.treeview.css");
|
||||
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
|
||||
$this->add_linked_stylesheet("../css/jquery-ui-timepicker-addon.css");
|
||||
$this->add_linked_stylesheet("../css/fg.menu.css");
|
||||
$this->add_linked_stylesheet("../css/jquery.multiselect.css");
|
||||
$this->add_linked_stylesheet("../css/magnific-popup.css");
|
||||
@@ -73,6 +74,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->add_linked_script("../js/jquery.treeview.js");
|
||||
$this->add_linked_script("../js/jquery.autocomplete.js");
|
||||
$this->add_linked_script("../js/date.js");
|
||||
$this->add_linked_script("../js/jquery-ui-timepicker-addon.js");
|
||||
$this->add_linked_script("../js/jquery-ui-timepicker-addon-i18n.min.js");
|
||||
$this->add_linked_script("../js/jquery.blockUI.js");
|
||||
$this->add_linked_script("../js/utils.js");
|
||||
$this->add_linked_script("../js/swfobject.js");
|
||||
@@ -83,8 +86,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->add_linked_script('../js/fg.menu.js');
|
||||
$this->add_linked_script('../js/icon_select.js');
|
||||
$this->add_linked_script('../js/raphael-min.js');
|
||||
$this->add_linked_script('../js/d3.min.js');
|
||||
$this->add_linked_script('../js/c3.min.js');
|
||||
$this->add_linked_script('../js/d3.js');
|
||||
$this->add_linked_script('../js/c3.js');
|
||||
$this->add_linked_script('../js/jquery.multiselect.js');
|
||||
$this->add_linked_script('../js/ajaxfileupload.js');
|
||||
$this->add_linked_script('../js/jquery.mousewheel.js');
|
||||
@@ -152,6 +155,11 @@ EOF;
|
||||
$sJSMonthsShort = json_encode(array(Dict::S('Month-01-Short'), Dict::S('Month-02-Short'), Dict::S('Month-03-Short'), Dict::S('Month-04-Short'), Dict::S('Month-05-Short'), Dict::S('Month-06-Short'),
|
||||
Dict::S('Month-07-Short'), Dict::S('Month-08-Short'), Dict::S('Month-09-Short'), Dict::S('Month-10-Short'), Dict::S('Month-11-Short'), Dict::S('Month-12-Short')));
|
||||
$iFirstDayOfWeek = (int) Dict::S('Calendar-FirstDayOfWeek');
|
||||
$sDateFormat = AttributeDate::GetDatePickerFormat();
|
||||
$sJSDateFormat = json_encode($sDateFormat);
|
||||
$sJSTimeFormat = json_encode(trim(str_replace($sDateFormat, '', AttributeDateTime::GetDatePickerFormat())));
|
||||
$sJSLangShort = json_encode(strtolower(substr(Dict::GetUserLanguage(), 0, 2)));
|
||||
$sJSOk = json_encode(Dict::S('UI:Button:Ok'));
|
||||
|
||||
$this->m_sInitScript =
|
||||
<<< EOF
|
||||
@@ -393,7 +401,7 @@ EOF
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd',
|
||||
dateFormat: $sJSDateFormat,
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
@@ -401,18 +409,28 @@ EOF
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
$(".datetime-pick").datepicker({
|
||||
$(".datetime-pick").datetimepicker({
|
||||
showOn: 'button',
|
||||
buttonImage: '../images/calendar.png',
|
||||
buttonImageOnly: true,
|
||||
dateFormat: 'yy-mm-dd 00:00:00',
|
||||
dateFormat: $sJSDateFormat,
|
||||
constrainInput: false,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dayNamesMin: $sJSDaysMin,
|
||||
monthNamesShort: $sJSMonthsShort,
|
||||
firstDay: $iFirstDayOfWeek
|
||||
});
|
||||
firstDay: $iFirstDayOfWeek,
|
||||
// time picker options
|
||||
timeFormat: $sJSTimeFormat,
|
||||
controlType: 'select',
|
||||
timeText: $.timepicker.regional[$sJSLangShort].timeText,
|
||||
hourText: $.timepicker.regional[$sJSLangShort].hourText,
|
||||
minuteText: $.timepicker.regional[$sJSLangShort].minuteText,
|
||||
secondText: $.timepicker.regional[$sJSLangShort].secondText,
|
||||
currentText: $.timepicker.regional[$sJSLangShort].currentText,
|
||||
closeText: $sJSOk
|
||||
});
|
||||
|
||||
|
||||
// Make sortable, everything that claims to be sortable
|
||||
$('.sortable').sortable( {axis: 'y', cursor: 'move', handle: '.drag_handle', stop: function()
|
||||
@@ -454,6 +472,11 @@ EOF
|
||||
EOF
|
||||
);
|
||||
$this->add_ready_script(InlineImage::FixImagesWidth());
|
||||
/*
|
||||
* Not used since the sorting of the tables is always performed server-side
|
||||
AttributeDateTime::InitTableSorter($this, 'custom_date_time');
|
||||
AttributeDate::InitTableSorter($this, 'custom_date');
|
||||
*/
|
||||
|
||||
$sUserPrefs = appUserPreferences::GetAsJSON();
|
||||
$this->add_script(
|
||||
|
||||
@@ -482,6 +482,19 @@ class utils
|
||||
}
|
||||
// http://www.spaweditor.com/scripts/regex/index.php
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an old date/time format specifciation (using % placeholders)
|
||||
* to a format compatible with DateTime::createFromFormat
|
||||
* @param string $sOldDateTimeFormat
|
||||
* @return string
|
||||
*/
|
||||
static public function DateTimeFormatToPHP($sOldDateTimeFormat)
|
||||
{
|
||||
$aSearch = array('%d', '%m', '%y', '%Y', '%H', '%i', '%s');
|
||||
$aReplacement = array('d', 'm', 'y', 'Y', 'H', 'i', 's');
|
||||
return str_replace($aSearch, $aReplacement, $sOldDateTimeFormat);
|
||||
}
|
||||
|
||||
static public function GetConfig()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,8 @@ Class XLSXWriter
|
||||
protected $shared_strings = array();//unique set
|
||||
protected $shared_string_count = 0;//count of non-unique references to the unique set
|
||||
protected $temp_files = array();
|
||||
protected $date_format = 'YYYY-MM-DD';
|
||||
protected $date_time_format = 'YYYY-MM-DD\ HH:MM:SS';
|
||||
|
||||
public function __construct(){}
|
||||
public function setAuthor($author='') { $this->author=$author; }
|
||||
@@ -26,6 +28,16 @@ Class XLSXWriter
|
||||
}
|
||||
}
|
||||
|
||||
public function setDateFormat($date_format)
|
||||
{
|
||||
$this->date_format = $date_format;
|
||||
}
|
||||
|
||||
public function setDateTimeFormat($date_time_format)
|
||||
{
|
||||
$this->date_time_format = $date_time_format;
|
||||
}
|
||||
|
||||
protected function tempFilename()
|
||||
{
|
||||
$filename = tempnam("/tmp", "xlsx_writer_");
|
||||
@@ -183,8 +195,8 @@ Class XLSXWriter
|
||||
fwrite($fd, '<numFmts count="4">');
|
||||
fwrite($fd, '<numFmt formatCode="GENERAL" numFmtId="164"/>');
|
||||
fwrite($fd, '<numFmt formatCode="[$$-1009]#,##0.00;[RED]\-[$$-1009]#,##0.00" numFmtId="165"/>');
|
||||
fwrite($fd, '<numFmt formatCode="YYYY-MM-DD\ HH:MM:SS" numFmtId="166"/>');
|
||||
fwrite($fd, '<numFmt formatCode="YYYY-MM-DD" numFmtId="167"/>');
|
||||
fwrite($fd, '<numFmt formatCode="'.$this->date_time_format.'" numFmtId="166"/>');
|
||||
fwrite($fd, '<numFmt formatCode="'.$this->date_format.'" numFmtId="167"/>');
|
||||
fwrite($fd, '</numFmts>');
|
||||
fwrite($fd, '<fonts count="4">');
|
||||
fwrite($fd, '<font><name val="Arial"/><charset val="1"/><family val="2"/><sz val="10"/></font>');
|
||||
|
||||
@@ -34,7 +34,7 @@ class ExecAsyncTask implements iBackgroundProcess
|
||||
|
||||
public function Process($iTimeLimit)
|
||||
{
|
||||
$sNow = date('Y-m-d H:i:s');
|
||||
$sNow = date(AttributeDateTime::GetSQLFormat());
|
||||
// Criteria: planned, and expected to occur... ASAP or in the past
|
||||
$sOQL = "SELECT AsyncTask WHERE (status = 'planned') AND (ISNULL(planned) OR (planned < '$sNow'))";
|
||||
$iProcessed = 0;
|
||||
|
||||
@@ -3537,9 +3537,353 @@ class AttributeMetaEnum extends AttributeEnum
|
||||
*/
|
||||
class AttributeDateTime extends AttributeDBField
|
||||
{
|
||||
static public function GetDateFormat()
|
||||
static $sDateTimeFormat = null;
|
||||
static $sTimeFormat = null;
|
||||
|
||||
static public function GetFormat()
|
||||
{
|
||||
return "Y-m-d H:i:s";
|
||||
if (self::$sDateTimeFormat == null)
|
||||
{
|
||||
static::LoadFormatFromConfig();
|
||||
}
|
||||
return self::$sDateTimeFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the 3 settings: date format, time format and data_time format from the configuration
|
||||
*/
|
||||
protected static function LoadFormatFromConfig()
|
||||
{
|
||||
$aFormats = MetaModel::GetConfig()->Get('date_and_time_format');
|
||||
$sLang = Dict::GetUserLanguage();
|
||||
$sDateFormat = isset($aFormats[$sLang]['date']) ? $aFormats[$sLang]['date'] : (isset($aFormats['default']['date']) ? $aFormats['default']['date'] : 'Y-m-d');
|
||||
$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);
|
||||
|
||||
self::SetFormat($sFormat);
|
||||
self::SetTimeFormat($sTimeFormat);
|
||||
AttributeDate::SetFormat($sDateFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format string used for the date & time stored in memory
|
||||
* @return string
|
||||
*/
|
||||
static public function GetInternalFormat()
|
||||
{
|
||||
return 'Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format string used for the date & time written to MySQL
|
||||
* @return string
|
||||
*/
|
||||
static public function GetSQLFormat()
|
||||
{
|
||||
return 'Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
static public function SetFormat($sDateTimeFormat)
|
||||
{
|
||||
self::$sDateTimeFormat = $sDateTimeFormat;
|
||||
}
|
||||
|
||||
static public function GetTimeFormat()
|
||||
{
|
||||
if (self::$sTimeFormat == null)
|
||||
{
|
||||
static::LoadFormatFromConfig();
|
||||
}
|
||||
return self::$sTimeFormat;
|
||||
}
|
||||
|
||||
static public function GetSQLTimeFormat()
|
||||
{
|
||||
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
|
||||
* @return string
|
||||
*/
|
||||
public static function Parse($sDate, $sFormat)
|
||||
{
|
||||
if (($sDate == null) || ($sDate == '0000-00-00 00:00:00') || ($sDate == '0000-00-00'))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sFormat = preg_replace('/\\?/', '', $sFormat); // replace escaped characters by a wildcard for parsing
|
||||
$oDate = DateTime::createFromFormat($sFormat, $sDate);
|
||||
if ($oDate === false)
|
||||
{
|
||||
throw new Exception("Unable to parse the date: '$sDate' using the format: '$sFormat'");
|
||||
}
|
||||
return $oDate->format(static::GetInternalFormat());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static public function GetDatePickerFormat()
|
||||
{
|
||||
$sFormat = static::GetFormat();
|
||||
$aMappings = static::GetFormatMapping();
|
||||
$sResult = '';
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
static public function ListExpectedParams()
|
||||
@@ -3550,6 +3894,12 @@ class AttributeDateTime extends AttributeDBField
|
||||
|
||||
public function GetEditClass() {return "DateTime";}
|
||||
|
||||
|
||||
public function GetEditValue($sValue, $oHostObj = null)
|
||||
{
|
||||
return (string)static::Format($sValue, static::GetFormat());
|
||||
}
|
||||
|
||||
protected function GetSQLCol($bFullSpec = false) {return "DATETIME";}
|
||||
public static function GetAsUnixSeconds($value)
|
||||
{
|
||||
@@ -3558,29 +3908,15 @@ class AttributeDateTime extends AttributeDBField
|
||||
return $iUnixSeconds;
|
||||
}
|
||||
|
||||
// This has been done at the time when itop was using TIMESTAMP columns,
|
||||
// now that iTop is using DATETIME columns, it seems possible to have IsNullAllowed returning false... later when this is needed
|
||||
public function IsNullAllowed() {return true;}
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
{
|
||||
$default = parent::GetDefaultValue($oHostObject);
|
||||
|
||||
if (!parent::IsNullAllowed())
|
||||
{
|
||||
if (empty($default))
|
||||
{
|
||||
$default = date($this->GetDateFormat());
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
// null value will be replaced by the current date, if not already set, in DoComputeValues
|
||||
return $this->GetNullValue();
|
||||
}
|
||||
// END OF THE WORKAROUND
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public function GetValidationPattern()
|
||||
{
|
||||
return "^(([0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30))))( (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9])){0,1}){0,1}|0000-00-00 00:00:00|0000-00-00)$";
|
||||
return static::GetRegExpr();
|
||||
}
|
||||
|
||||
public function GetBasicFilterOperators()
|
||||
@@ -3654,7 +3990,7 @@ class AttributeDateTime extends AttributeDBField
|
||||
return $proposedValue;
|
||||
}
|
||||
|
||||
return date(self::GetDateFormat(), $proposedValue);
|
||||
return date(self::GetInternalFormat(), $proposedValue);
|
||||
}
|
||||
|
||||
public function ScalarToSQL($value)
|
||||
@@ -3673,7 +4009,7 @@ class AttributeDateTime extends AttributeDBField
|
||||
|
||||
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
|
||||
{
|
||||
return Str::pure2html($value);
|
||||
return Str::pure2html(static::Format($value, static::GetFormat()));
|
||||
}
|
||||
|
||||
public function GetAsXML($value, $oHostObject = null, $bLocalize = true)
|
||||
@@ -3683,6 +4019,19 @@ class AttributeDateTime extends AttributeDBField
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false)
|
||||
{
|
||||
if (empty($sValue) || ($sValue === '0000-00-00 00:00:00') || ($sValue === '0000-00-00'))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
else if (self::GetFormat() !== self::GetInternalFormat())
|
||||
{
|
||||
// Format conversion
|
||||
$oDate = new DateTime($sValue);
|
||||
if ($oDate !== false)
|
||||
{
|
||||
$sValue = $oDate->format(self::GetFormat());
|
||||
}
|
||||
}
|
||||
$sFrom = array("\r\n", $sTextQualifier);
|
||||
$sTo = array("\n", $sTextQualifier.$sTextQualifier);
|
||||
$sEscaped = str_replace($sFrom, $sTo, (string)$sValue);
|
||||
@@ -3839,13 +4188,40 @@ class AttributeDuration extends AttributeInteger
|
||||
*/
|
||||
class AttributeDate extends AttributeDateTime
|
||||
{
|
||||
const MYDATEFORMAT = "Y-m-d";
|
||||
|
||||
static public function GetDateFormat()
|
||||
static $sDateFormat = null;
|
||||
|
||||
static public function GetFormat()
|
||||
{
|
||||
return "Y-m-d";
|
||||
if (self::$sDateFormat == null)
|
||||
{
|
||||
AttributeDateTime::LoadFormatFromConfig();
|
||||
}
|
||||
return self::$sDateFormat;
|
||||
}
|
||||
|
||||
static public function SetFormat($sDateFormat)
|
||||
{
|
||||
self::$sDateFormat = $sDateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format string used for the date & time stored in memory
|
||||
* @return string
|
||||
*/
|
||||
static public function GetInternalFormat()
|
||||
{
|
||||
return 'Y-m-d';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format string used for the date & time written to MySQL
|
||||
* @return string
|
||||
*/
|
||||
static public function GetSQLFormat()
|
||||
{
|
||||
return 'Y-m-d';
|
||||
}
|
||||
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return parent::ListExpectedParams();
|
||||
@@ -3854,11 +4230,6 @@ class AttributeDate extends AttributeDateTime
|
||||
|
||||
public function GetEditClass() {return "Date";}
|
||||
protected function GetSQLCol($bFullSpec = false) {return "DATE";}
|
||||
|
||||
public function GetValidationPattern()
|
||||
{
|
||||
return "^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -258,7 +258,7 @@ class BulkChange
|
||||
protected $m_aReconcilKeys; // attcode (attcode = 'id' for the pkey)
|
||||
protected $m_sSynchroScope; // OQL - if specified, then the missing items will be reported
|
||||
protected $m_aOnDisappear; // array of attcode => value, values to be set when an object gets out of scope (ignored if no scope has been defined)
|
||||
protected $m_sDateFormat; // Date format specification, see utils::StringToTime()
|
||||
protected $m_sDateFormat; // Date format specification, see DateTime::createFromFormat
|
||||
protected $m_bLocalizedValues; // Values in the data set are localized (see AttributeEnum)
|
||||
protected $m_aExtKeysMappingCache; // Cache for resolving external keys based on the given search criterias
|
||||
|
||||
@@ -800,16 +800,16 @@ class BulkChange
|
||||
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
||||
{
|
||||
if ($sAttCode == 'id') continue;
|
||||
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
foreach($this->m_aData as $iRow => $aRowData)
|
||||
{
|
||||
$sNewDate = utils::StringToTime($this->m_aData[$iRow][$iCol], $this->m_sDateFormat);
|
||||
if ($sNewDate !== false)
|
||||
$oDate = DateTime::createFromFormat($this->m_sDateFormat, $this->m_aData[$iRow][$iCol]);
|
||||
if ($oDate !== false)
|
||||
{
|
||||
// Todo - improve the reporting
|
||||
$sNewDate = $oDate->format($oAttDef->GetInternalFormat());
|
||||
$this->m_aData[$iRow][$iCol] = $sNewDate;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -95,7 +95,7 @@ class BulkExportResultGC implements iBackgroundProcess
|
||||
|
||||
public function Process($iTimeLimit)
|
||||
{
|
||||
$sDateLimit = date('Y-m-d H:i:s', time() - 24*3600); // Every BulkExportResult older than one day will be deleted
|
||||
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time() - 24*3600); // Every BulkExportResult older than one day will be deleted
|
||||
|
||||
$sOQL = "SELECT BulkExportResult WHERE created < '$sDateLimit'";
|
||||
$iProcessed = 0;
|
||||
|
||||
@@ -898,6 +898,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'date_and_time_format' => array(
|
||||
'type' => 'array',
|
||||
'description' => 'Format for date and time display (per language)',
|
||||
'default' => array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')),
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
);
|
||||
|
||||
public function IsProperty($sPropCode)
|
||||
|
||||
@@ -34,6 +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'");
|
||||
}
|
||||
|
||||
public function ReadParameters()
|
||||
@@ -57,6 +58,16 @@ 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')
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +108,7 @@ class CSVBulkExport extends TabularBulkExport
|
||||
$oP->add('<table class="export_parameters"><tr><td style="vertical-align:top">');
|
||||
$oP->add('<h3>'.Dict::S('UI:CSVImport:SeparatorCharacter').'</h3>');
|
||||
$sRawSeparator = utils::ReadParam('separator', ',', true, 'raw_data');
|
||||
$sCustomDateTimeFormat = utils::ReadParam('', ',', true, 'raw_data');
|
||||
$aSep = array(
|
||||
';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'),
|
||||
',' => Dict::S('UI:CSVImport:SeparatorComma+'),
|
||||
@@ -162,10 +174,28 @@ class CSVBulkExport extends TabularBulkExport
|
||||
$sChecked = (utils::ReadParam('formatted_text', 0) == 1) ? ' checked ' : '';
|
||||
$oP->add('<h3>'.Dict::S('Core:BulkExport:TextFormat').'</h3>');
|
||||
$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' : '';
|
||||
$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');
|
||||
$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>');
|
||||
$oP->add('</td></tr></table>');
|
||||
|
||||
$oP->add('</fieldset>');
|
||||
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#csv_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
|
||||
$('#csv_custom_date_time_format').on('click', function() { $('#csv_date_time_format_custom').prop('checked', true); });
|
||||
EOF
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -257,7 +287,10 @@ class CSVBulkExport extends TabularBulkExport
|
||||
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')
|
||||
|
||||
@@ -705,6 +705,17 @@ abstract class DBObject implements iDisplay
|
||||
if ($aCallInfo["function"] != "ComputeValues") continue;
|
||||
return; //skip!
|
||||
}
|
||||
|
||||
// Set the "null-not-allowed" datetimes (and dates) whose value is not initialized
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
||||
{
|
||||
// AttributeDate is derived from AttributeDateTime
|
||||
if (($oAttDef instanceof AttributeDateTime) && (!$oAttDef->IsNullAllowed()) && ($this->Get($sAttCode) == $oAttDef->GetNullValue()))
|
||||
{
|
||||
$this->Set($sAttCode, date($oAttDef->GetFormat()));
|
||||
}
|
||||
}
|
||||
|
||||
$this->ComputeValues();
|
||||
}
|
||||
|
||||
@@ -3300,8 +3311,8 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
$aContext['current_contact_id'] = UserRights::GetContactId();
|
||||
$aContext['current_contact_friendlyname'] = UserRights::GetUserFriendlyName();
|
||||
$aContext['current_date'] = date('Y-m-d');
|
||||
$aContext['current_time'] = date('H:i:s');
|
||||
$aContext['current_date'] = date(AttributeDate::GetSQLFormat());
|
||||
$aContext['current_time'] = date(AttributeDateTime::GetSQLTimeFormat());
|
||||
$sValue = MetaModel::ApplyParams($sRawValue, $aContext);
|
||||
$this->Set($sAttCode, $sValue);
|
||||
break;
|
||||
@@ -3328,8 +3339,8 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
$aContext['current_contact_id'] = UserRights::GetContactId();
|
||||
$aContext['current_contact_friendlyname'] = UserRights::GetUserFriendlyName();
|
||||
$aContext['current_date'] = date('Y-m-d');
|
||||
$aContext['current_time'] = date('H:i:s');
|
||||
$aContext['current_date'] = date(AttributeDate::GetSQLFormat());
|
||||
$aContext['current_time'] = date(AttributeDateTime::GetSQLTimeFormat());
|
||||
$sAddendum = MetaModel::ApplyParams($sRawAddendum, $aContext);
|
||||
$this->Set($sAttCode, $this->Get($sAttCode).$sAddendum);
|
||||
break;
|
||||
|
||||
@@ -47,12 +47,23 @@ 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'");
|
||||
}
|
||||
|
||||
public function ReadParameters()
|
||||
{
|
||||
parent::ReadParameters();
|
||||
$this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true);
|
||||
|
||||
$sDateFormatRadio = utils::ReadParam('date_format_radio', 'custom');
|
||||
if ($sDateFormatRadio == 'default')
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
|
||||
}
|
||||
}
|
||||
|
||||
public function EnumFormParts()
|
||||
@@ -76,9 +87,28 @@ class ExcelBulkExport extends TabularBulkExport
|
||||
$oP->add('<h3>'.Dict::S('Core:BulkExport:TextFormat').'</h3>');
|
||||
$oP->add('<input type="checkbox" id="xlsx_formatted_text" name="formatted_text" value="1"'.$sChecked.'><label for="xlsx_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' : '';
|
||||
$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');
|
||||
$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>');
|
||||
|
||||
$oP->add('</td></tr></table>');
|
||||
|
||||
$oP->add('</fieldset>');
|
||||
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#excel_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
|
||||
$('#excel_custom_date_time_format').on('click', function() { $('#excel_date_time_format_custom').prop('checked', true); });
|
||||
EOF
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -141,14 +171,19 @@ class ExcelBulkExport extends TabularBulkExport
|
||||
else
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||
if (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text'])
|
||||
{
|
||||
if ($oAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
// Date and times are formatted using the ISO encoding, not the localized format
|
||||
$sRet = $value;
|
||||
}
|
||||
else if (array_key_exists('formatted_text', $this->aStatusInfo) && $this->aStatusInfo['formatted_text'])
|
||||
{
|
||||
$sRet = $oAttDef->GetEditValue($value, $oObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRet = $oAttDef->GetAsPlainText($value, $oObj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRet = $oAttDef->GetAsPlainText($value, $oObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $sRet;
|
||||
@@ -269,6 +304,7 @@ class ExcelBulkExport extends TabularBulkExport
|
||||
|
||||
$fStartExcel = microtime(true);
|
||||
$writer = new XLSXWriter();
|
||||
$writer->setDateTimeFormat(AttributeDateTime::GetExcelFormat($this->aStatusInfo['date_format']));
|
||||
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
||||
$aHeaderTypes = array();
|
||||
$aHeaderNames = array();
|
||||
|
||||
@@ -488,7 +488,7 @@ class InlineImageGC implements iBackgroundProcess
|
||||
|
||||
public function Process($iTimeLimit)
|
||||
{
|
||||
$sDateLimit = date('Y-m-d H:i:s', time()); // Every temporary InlineImage/Attachment expired will be deleted
|
||||
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time()); // Every temporary InlineImage/Attachment expired will be deleted
|
||||
|
||||
$iProcessed = 0;
|
||||
$sOQL = "SELECT InlineImage WHERE (item_id = 0) AND (expire < '$sDateLimit')";
|
||||
|
||||
@@ -115,14 +115,14 @@ class ormCaseLog {
|
||||
if (is_int($this->m_aIndex[$index]['date']))
|
||||
{
|
||||
// Unix timestamp
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'),$this->m_aIndex[$index]['date']);
|
||||
$sDate = date(AttributeDateTime::GetInternalFormat(),$this->m_aIndex[$index]['date']);
|
||||
}
|
||||
elseif (is_object($this->m_aIndex[$index]['date']))
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>='))
|
||||
{
|
||||
// DateTime
|
||||
$sDate = $this->m_aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
|
||||
$sDate = $this->m_aIndex[$index]['date']->format(AttributeDateTime::GetInternalFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -234,14 +234,14 @@ class ormCaseLog {
|
||||
if (is_int($aIndex[$index]['date']))
|
||||
{
|
||||
// Unix timestamp
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'),$aIndex[$index]['date']);
|
||||
$sDate = date(AttributeDateTime::GetFormat(), $aIndex[$index]['date']);
|
||||
}
|
||||
elseif (is_object($aIndex[$index]['date']))
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>='))
|
||||
{
|
||||
// DateTime
|
||||
$sDate = $aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
|
||||
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -322,14 +322,14 @@ class ormCaseLog {
|
||||
if (is_int($aIndex[$index]['date']))
|
||||
{
|
||||
// Unix timestamp
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'),$aIndex[$index]['date']);
|
||||
$sDate = date(AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
|
||||
}
|
||||
elseif (is_object($aIndex[$index]['date']))
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>='))
|
||||
{
|
||||
// DateTime
|
||||
$sDate = $aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
|
||||
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -425,14 +425,14 @@ class ormCaseLog {
|
||||
if (is_int($aIndex[$index]['date']))
|
||||
{
|
||||
// Unix timestamp
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'),$aIndex[$index]['date']);
|
||||
$sDate = date(AttributeDateTime::GetFormat(),$aIndex[$index]['date']);
|
||||
}
|
||||
elseif (is_object($aIndex[$index]['date']))
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>='))
|
||||
{
|
||||
// DateTime
|
||||
$sDate = $aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
|
||||
$sDate = $aIndex[$index]['date']->format(AttributeDateTime::GetFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -498,7 +498,7 @@ class ormCaseLog {
|
||||
{
|
||||
$sText = HTMLSanitizer::Sanitize($sText);
|
||||
$bMergeEntries = false;
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'));
|
||||
$sDate = date(AttributeDateTime::GetInternalFormat());
|
||||
if ($sOnBehalfOf == '')
|
||||
{
|
||||
$sOnBehalfOf = UserRights::GetUserFriendlyName();
|
||||
@@ -612,7 +612,7 @@ class ormCaseLog {
|
||||
$sFormat = 'html';
|
||||
}
|
||||
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'), $iDate);
|
||||
$sDate = date(AttributeDateTime::GetInternalFormat(), $iDate);
|
||||
|
||||
$sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId);
|
||||
$iSepLength = strlen($sSeparator);
|
||||
|
||||
@@ -490,7 +490,7 @@ class CheckStopWatchThresholds implements iBackgroundProcess
|
||||
{
|
||||
$iPercent = $aThresholdData['percent']; // could be different than the index !
|
||||
|
||||
$sNow = date('Y-m-d H:i:s');
|
||||
$sNow = date(AttributeDateTime::GetSQLFormat());
|
||||
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '$sNow'";
|
||||
$oFilter = DBObjectSearch::FromOQL($sExpression);
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
|
||||
@@ -239,7 +239,7 @@ class iTopOwnershipLock
|
||||
{
|
||||
if ($sToken === $this->oToken->Get('token'))
|
||||
{
|
||||
$this->oToken->Set('last_seen', date('Y-m-d H:i:s'));
|
||||
$this->oToken->Set('last_seen', date(AttributeDateTime::GetSQLFormat()));
|
||||
$this->oToken->DBUpdate();
|
||||
$aResult['acquired'] = $this->oToken->Get('acquired');
|
||||
}
|
||||
@@ -327,9 +327,9 @@ class iTopOwnershipLock
|
||||
$this->oToken->Set('obj_class', $this->sObjClass);
|
||||
$this->oToken->Set('obj_key', $this->iObjKey);
|
||||
}
|
||||
$this->oToken->Set('acquired', date('Y-m-d H:i:s'));
|
||||
$this->oToken->Set('acquired', date(AttributeDateTime::GetSQLFormat()));
|
||||
$this->oToken->Set('user_id', UserRights::GetUserId());
|
||||
$this->oToken->Set('last_seen', date('Y-m-d H:i:s'));
|
||||
$this->oToken->Set('last_seen', date(AttributeDateTime::GetSQLFormat()));
|
||||
if ($sToken === null)
|
||||
{
|
||||
$sToken = sprintf('%X', microtime(true));
|
||||
@@ -342,7 +342,7 @@ class iTopOwnershipLock
|
||||
protected static function DeleteExpiredLocks()
|
||||
{
|
||||
$sOQL = "SELECT iTopOwnershipToken WHERE last_seen < :last_seen_limit";
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL, array('last_seen_limit' => date('Y-m-d H:i:s', time() - MetaModel::GetConfig()->Get('concurrent_lock_expiration_delay')))));
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL, array('last_seen_limit' => date(AttributeDateTime::GetSQLFormat(), time() - MetaModel::GetConfig()->Get('concurrent_lock_expiration_delay')))));
|
||||
while($oToken = $oSet->Fetch())
|
||||
{
|
||||
$oToken->DBDelete();
|
||||
|
||||
@@ -31,6 +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'");
|
||||
}
|
||||
|
||||
public function EnumFormParts()
|
||||
@@ -44,6 +45,8 @@ class PDFBulkExport extends HTMLBulkExport
|
||||
{
|
||||
case 'pdf_options':
|
||||
$oP->add('<fieldset><legend>'.Dict::S('Core:BulkExport:PDFOptions').'</legend>');
|
||||
$oP->add('<table class="export_parameters"><tr><td style="vertical-align:top">');
|
||||
$oP->add('<h3>'.Dict::S('Core:PDFBulkExport:PageFormat').'</h3>');
|
||||
$oP->add('<table>');
|
||||
$oP->add('<tr>');
|
||||
$oP->add('<td>'.Dict::S('Core:BulkExport:PDFPageSize').'</td>');
|
||||
@@ -53,8 +56,30 @@ class PDFBulkExport extends HTMLBulkExport
|
||||
$oP->add('<td>'.$this->GetSelectCtrl('page_orientation', array('P', 'L'), 'Core:BulkExport:PageOrientation-', 'L').'</td>');
|
||||
$oP->add('</tr>');
|
||||
$oP->add('</table>');
|
||||
|
||||
|
||||
$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' : '';
|
||||
$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');
|
||||
$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>');
|
||||
|
||||
$oP->add('</td></tr></table>');
|
||||
|
||||
|
||||
$oP->add('</fieldset>');
|
||||
$sJSTooltip = json_encode('<div id="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#pdf_custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
|
||||
$('#pdf_custom_date_time_format').on('click', function() { $('#pdf_date_time_format_custom').prop('checked', true); });
|
||||
EOF
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -88,6 +113,16 @@ class PDFBulkExport extends HTMLBulkExport
|
||||
parent::ReadParameters();
|
||||
$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')
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = AttributeDateTime::GetFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aStatusInfo['date_format'] = utils::ReadParam('date_format', AttributeDateTime::GetFormat(), true, 'raw_data');
|
||||
}
|
||||
}
|
||||
|
||||
public function GetHeader()
|
||||
@@ -106,7 +141,10 @@ class PDFBulkExport extends HTMLBulkExport
|
||||
|
||||
public function GetNextChunk(&$aStatus)
|
||||
{
|
||||
$sPrevFormat = AttributeDateTime::GetFormat();
|
||||
AttributeDateTime::SetFormat($this->aStatusInfo['date_format']);
|
||||
$sData = parent::GetNextChunk($aStatus);
|
||||
AttributeDateTime::SetFormat($sPrevFormat);
|
||||
$hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab');
|
||||
if ($hFile === false)
|
||||
{
|
||||
|
||||
30
css/jquery-ui-timepicker-addon.css
Normal file
30
css/jquery-ui-timepicker-addon.css
Normal file
@@ -0,0 +1,30 @@
|
||||
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
|
||||
.ui-timepicker-div dl { text-align: left; }
|
||||
.ui-timepicker-div dl dt { float: left; clear:left; padding: 0 0 0 5px; }
|
||||
.ui-timepicker-div dl dd { margin: 0 10px 10px 40%; }
|
||||
.ui-timepicker-div td { font-size: 90%; }
|
||||
.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
|
||||
.ui-timepicker-div .ui_tpicker_unit_hide{ display: none; }
|
||||
|
||||
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { background: none; color: inherit; border: none; outline: none; border-bottom: solid 1px #555; width: 95%; }
|
||||
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { border-bottom-color: #aaa; }
|
||||
|
||||
.ui-timepicker-rtl{ direction: rtl; }
|
||||
.ui-timepicker-rtl dl { text-align: right; padding: 0 5px 0 0; }
|
||||
.ui-timepicker-rtl dl dt{ float: right; clear: right; }
|
||||
.ui-timepicker-rtl dl dd { margin: 0 40% 10px 10px; }
|
||||
|
||||
/* Shortened version style */
|
||||
.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { content:'.'; display:inline-block; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{ display: none; }
|
||||
@@ -2268,3 +2268,14 @@ span.refresh-button {
|
||||
}
|
||||
|
||||
|
||||
.ui-datepicker-buttonpane, .ui-timepicker-div {
|
||||
font-size: 9pt;
|
||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||
}
|
||||
|
||||
|
||||
.date_format_tooltip td {
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1695,3 +1695,10 @@ span.refresh-button {
|
||||
}
|
||||
}
|
||||
}
|
||||
.ui-datepicker-buttonpane, .ui-timepicker-div {
|
||||
font-size: 9pt;
|
||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||
}
|
||||
.date_format_tooltip td {
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,6 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'UI:FailedToApplyStimuli' => 'Akce se nezdařila.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Upravuji %2$d objekt(ů) třídy %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Zadejte text zde:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Počáteční hodnota:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Pole %1$s není zapisovatelné, protože je spravováno synchronizací dat.',
|
||||
|
||||
@@ -840,7 +840,6 @@ Ved tilknytningen til en trigger, bliver hver handling tildelt et "rækkefølge"
|
||||
'UI:FailedToApplyStimuli' => 'Handlingen fejlede.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Ændrer %2$d objekter af klasse %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Skriv din tekst her:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Begyndelses værdi:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Feltet %1$s er skrivebeskyttet, fordi det administreres af data synchronization. Værdien er ikke sat.',
|
||||
|
||||
@@ -861,7 +861,6 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm
|
||||
'UI:FailedToApplyStimuli' => 'Der Vorgang ist fehlgeschlagen.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifiziere %2$d Objekte der Klasse %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Geben Sie Ihren Text hier ein:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Anfangswert:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Das Feld %1$s ist nicht schreibbar, weil es durch die Datensynchronisation geführt wird. Wert nicht gesetzt.',
|
||||
|
||||
@@ -853,4 +853,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Core:BulkExportLegacyExport' => 'Click here to access the legacy export.',
|
||||
'Core:BulkExport:XLSXOptions' => 'Excel Options',
|
||||
'Core:BulkExport:TextFormat' => 'Text fields containing some HTML markup',
|
||||
'Core:BulkExport:DateTimeFormat' => 'Date and Time format',
|
||||
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s',
|
||||
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s',
|
||||
));
|
||||
|
||||
@@ -1053,7 +1053,6 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:FailedToApplyStimuli' => 'The action has failed.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifying %2$d objects of class %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Type your text here:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Initial value:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value not set.',
|
||||
@@ -1255,7 +1254,26 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:CSVImportCreated_items' => 'Created: %1$d',
|
||||
'UI:CSVImportModified_items' => 'Modified: %1$d',
|
||||
'UI:CSVImportUnchanged_items' => 'Unchanged: %1$d',
|
||||
|
||||
'UI:CSVImport:DateAndTimeFormats' => 'Date and time format',
|
||||
'UI:CSVImport:DefaultDateTimeFormat_Format_Example' => 'Default format: %1$s (e.g. %2$s)',
|
||||
'UI:CSVImport:CustomDateTimeFormat' => 'Custom format: %1$s',
|
||||
'UI:CSVImport:CustomDateTimeFormatTooltip' => 'Available placeholders:<table>
|
||||
<tr><td>Y</td><td>year (4 digits, e.g. 2016)</td></tr>
|
||||
<tr><td>y</td><td>year (2 digits, e.g. 16 for 2016)</td></tr>
|
||||
<tr><td>m</td><td>month (2 digits, e.g. 01..12)</td></tr>
|
||||
<tr><td>n</td><td>month (1 or 2 digits no leading zero, e.g. 1..12)</td></tr>
|
||||
<tr><td>d</td><td>day (2 digits, e.g. 01..31)</td></tr>
|
||||
<tr><td>j</td><td>day (1 or 2 digits no leading zero, e.g. 1..31)</td></tr>
|
||||
<tr><td>H</td><td>hour (24 hour, 2 digits, e.g. 00..23)</td></tr>
|
||||
<tr><td>h</td><td>hour (12 hour, 2 digits, e.g. 01..12)</td></tr>
|
||||
<tr><td>G</td><td>hour (24 hour, 1 or 2 digits no leading zero, e.g. 0..23)</td></tr>
|
||||
<tr><td>g</td><td>hour (12 hour, 1 or 2 digits no leading zero, e.g. 1..12)</td></tr>
|
||||
<tr><td>a</td><td>hour, am or pm (lowercase)</td></tr>
|
||||
<tr><td>A</td><td>hour, AM or PM (uppercase)</td></tr>
|
||||
<tr><td>i</td><td>minutes (2 digits, e.g. 00..59)</td></tr>
|
||||
<tr><td>s</td><td>seconds (2 digits, e.g. 00..59)</td></tr>
|
||||
</table>',
|
||||
|
||||
'UI:Button:Remove' => 'Remove',
|
||||
'UI:AddAnExisting_Class' => 'Add objects of type %1$s...',
|
||||
'UI:SelectionOf_Class' => 'Selection of objects of type %1$s',
|
||||
|
||||
@@ -1017,7 +1017,6 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden",
|
||||
'UI:FailedToApplyStimuli' => 'La acción ha fallado.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modificando %2$d objetos de la clase %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Escriba su texto aquí:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Valor inicial:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'El campo %1$s no es escribible porque es manejado por el sincronizador de datos. Valor no cambiado.',
|
||||
|
||||
@@ -711,6 +711,9 @@ Opérateurs :<br/>
|
||||
'Core:BulkExportLegacyExport' => 'Cliquez ici pour exécuter l\'ancienne version de l\'export.',
|
||||
'Core:BulkExport:XLSXOptions' => 'Options du format Excel',
|
||||
'Core:BulkExport:TextFormat' => 'Champs texte contenant des balises HTML',
|
||||
'Core:BulkExport:DateTimeFormat' => 'Format de date et heure',
|
||||
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Format par défaut (%1$s), ex. %2$s',
|
||||
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Format spécial: %1$s',
|
||||
'Core:DeletedObjectLabel' => '%1s (effacé)',
|
||||
'Core:SyncSplitModeCLIOnly' => 'The synchronization can be executed in chunks only if run in mode CLI~~',
|
||||
'Core:ExecProcess:Code1' => 'Wrong command or command finished with errors (e.g. wrong script name)~~',
|
||||
|
||||
@@ -456,6 +456,25 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI:CSVImport:AlertMultipleMapping' => 'Veuillez vous assurer que chaque champ cible est sélectionné une seule fois.',
|
||||
'UI:CSVImport:AlertNoSearchCriteria' => 'Veuillez choisir au moins une clef de recherche.',
|
||||
'UI:CSVImport:Encoding' => 'Encodage des caractères',
|
||||
'UI:CSVImport:DateAndTimeFormats' => 'Format de date et heure',
|
||||
'UI:CSVImport:DefaultDateTimeFormat_Format_Example' => 'Format par défaut: %1$s (ex. %2$s)',
|
||||
'UI:CSVImport:CustomDateTimeFormat' => 'Format spécial: %1$s',
|
||||
'UI:CSVImport:CustomDateTimeFormatTooltip' => 'Codes de format:<table>
|
||||
<tr><td>Y</td><td>année (sur 4 chiffres, ex. 2016)</td></tr>
|
||||
<tr><td>y</td><td>année (sur 2 chiffres, ex. 16 pour 2016)</td></tr>
|
||||
<tr><td>m</td><td>mois (sur 2 chiffres: 01..12)</td></tr>
|
||||
<tr><td>n</td><td>month (sur 1 ou 2 chiffres sans le zero au début: 1..12)</td></tr>
|
||||
<tr><td>d</td><td>jour (sur 2 chiffres: 01..31)</td></tr>
|
||||
<tr><td>j</td><td>jour (sur 1 ou 2 chiffres sans le zero au début: 1..31)</td></tr>
|
||||
<tr><td>H</td><td>heure (24 heures sur 2 chiffres: 00..23)</td></tr>
|
||||
<tr><td>h</td><td>heure (12 heures sur 2 chiffres: 01..12)</td></tr>
|
||||
<tr><td>G</td><td>heure (24 heures sur 1 ou 2 chiffres: 0..23)</td></tr>
|
||||
<tr><td>g</td><td>heure (12 heures sur 1 ou 2 chiffres: 1..12)</td></tr>
|
||||
<tr><td>a</td><td>am ou pm (en minuscules)</td></tr>
|
||||
<tr><td>A</td><td>AM ou PM (en majuscules)</td></tr>
|
||||
<tr><td>i</td><td>minutes (sur 2 chiffres: 00..59)</td></tr>
|
||||
<tr><td>s</td><td>secondes (sur 2 chiffres: 00..59)</td></tr>
|
||||
</table>',
|
||||
|
||||
'UI:CSVReport-Value-Modified' => 'Modifié',
|
||||
'UI:CSVReport-Value-SetIssue' => 'Modification impossible - cause : %1$s',
|
||||
@@ -897,7 +916,6 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'UI:FailedToApplyStimuli' => 'L\'action a échoué',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modification de %2$d objet(s) de type %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Nouvelle entrée ci-dessous:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Valeur initiale:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Le champ %1$s ne peut pas être modifié car il est géré par une synchronisation avec une source de données. Valeur ignorée.',
|
||||
|
||||
@@ -760,7 +760,6 @@ Akció kiváltó okhoz rendelésekor kap egy sorszámot , amely meghatározza az
|
||||
'UI:FailedToApplyStimuli' => 'A művelet sikertelen',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: %3$s osztály %2$d objketumainak módosítása',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Írjon ide:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Kezdeti érték:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => '%1$s mező nem írható, mert a szinkronizációnál használt kulcs. Érték nem lett beállítva.',
|
||||
|
||||
@@ -894,7 +894,6 @@ Quando è associata a un trigger, ad ogni azione è assegnato un numero "ordine"
|
||||
'UI:FailedToApplyStimuli' => 'L\'azione non è riuscita.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifica %2$d oggetti della classe %3$s~~',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Digitare il tuo testo qui:',
|
||||
'UI:CaseLog:DateFormat' => 'A-m-g H:m:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:~~',
|
||||
'UI:CaseLog:InitialValue' => 'Valore iniziale:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Il campo %1$s on è scrivibile, perché è comandato dalla sincronizzazione dei dati. Valore non impostato.',
|
||||
|
||||
@@ -839,7 +839,6 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'UI:FailedToApplyStimuli' => 'アクションは失敗しました。',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: クラス%3$sの%2$dオブジェクトを修正',
|
||||
'UI:CaseLogTypeYourTextHere' => 'テキストを入力ください:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => '初期値:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'フィールド %1$s は、データの同期によってマスターリングされているため書き込み可能ではありません。値は設定されません。',
|
||||
|
||||
@@ -1025,7 +1025,6 @@ Indien gekoppeld aan een Trigger, wordt aan elke actie een "orde" nummer gegeven
|
||||
'UI:FailedToApplyStimuli' => 'De actie is mislukt.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Bezig met het bewerken van %2$d objecten van klasse %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Typ uw text hier:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Initiële waarde:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'Het veld %1$s is niet beschrijfbaar omdat het onderdeel is van de data synchronisatie. Waarde niet opgegeven',
|
||||
|
||||
@@ -1016,7 +1016,6 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:FailedToApplyStimuli' => 'A ação falhou.',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: modificando objetos %2$d da classe %3$s',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Digite seu texto aqui:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Valor inicial:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'O campo %1$s não é editável, porque é originado pela sincronização de dados. Valor não definido.',
|
||||
|
||||
@@ -1010,7 +1010,6 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'UI:FailedToApplyStimuli' => 'The action has failed.~~',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifying %2$d objects of class %3$s~~',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Введите свой текст:',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s~~',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:~~',
|
||||
'UI:CaseLog:InitialValue' => 'Initial value:~~',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value not set.~~',
|
||||
|
||||
@@ -1041,7 +1041,6 @@ Tetikleme gerçekleştiriğinde işlemler tanımlanan sıra numarası ile gerçe
|
||||
'UI:FailedToApplyStimuli' => 'The action has failed.~~',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifying %2$d objects of class %3$s~~',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Type your text here:~~',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s~~',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:~~',
|
||||
'UI:CaseLog:InitialValue' => 'Initial value:~~',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value not set.~~',
|
||||
|
||||
@@ -1040,7 +1040,6 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'UI:FailedToApplyStimuli' => 'The action has failed.~~',
|
||||
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifying %2$d objects of class %3$s~~',
|
||||
'UI:CaseLogTypeYourTextHere' => 'Type your text here:~~',
|
||||
'UI:CaseLog:DateFormat' => 'Y-m-d H:i:s~~',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:~~',
|
||||
'UI:CaseLog:InitialValue' => 'Initial value:~~',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value not set.~~',
|
||||
|
||||
4
js/jquery-ui-timepicker-addon-i18n.min.js
vendored
Normal file
4
js/jquery-ui-timepicker-addon-i18n.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2269
js/jquery-ui-timepicker-addon.js
vendored
Normal file
2269
js/jquery-ui-timepicker-addon.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -209,6 +209,11 @@ try
|
||||
$bAdvanced = utils::ReadParam('advanced', 0);
|
||||
$sEncoding = utils::ReadParam('encoding', 'UTF-8');
|
||||
$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
|
||||
$sDateTimeFormat = utils::ReadParam('date_time_format', 'default');
|
||||
$sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', AttributeDateTime::GetFormat(), false, 'raw_data');
|
||||
|
||||
$sChosenDateFormat = ($sDateTimeFormat == 'default') ? AttributeDateTime::GetFormat() : $sCustomDateTimeFormat;
|
||||
|
||||
if (!empty($sSynchroScope))
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL($sSynchroScope);
|
||||
@@ -319,7 +324,7 @@ try
|
||||
array_keys($aSearchKeys),
|
||||
empty($sSynchroScope) ? null : $sSynchroScope,
|
||||
$aSynchroUpdate,
|
||||
null, // date format
|
||||
$sChosenDateFormat, // date format
|
||||
true // localize
|
||||
);
|
||||
$oBulk->SetReportHtml();
|
||||
@@ -498,6 +503,8 @@ try
|
||||
$oPage->add('<input type="hidden" name="advanced" value="'.$bAdvanced.'"/>');
|
||||
$oPage->add('<input type="hidden" name="encoding" value="'.$sEncoding.'"/>');
|
||||
$oPage->add('<input type="hidden" name="synchro_scope" value="'.$sSynchroScope.'"/>');
|
||||
$oPage->add('<input type="hidden" name="date_time_format" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
$oPage->add('<input type="hidden" name="custom_date_time_format" value="'.htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
if (!empty($sSynchroScope))
|
||||
{
|
||||
foreach($aSynchroUpdate as $sKey => $value)
|
||||
@@ -658,7 +665,7 @@ function DoSubmit(bConfirm)
|
||||
created: $sCreated,
|
||||
modified: $sModified,
|
||||
unchanged: $sUnchanged
|
||||
}
|
||||
},
|
||||
type: 'donut'
|
||||
},
|
||||
legend: {
|
||||
@@ -754,6 +761,8 @@ EOF
|
||||
$sClassName = utils::ReadParam('class_name', '', false, 'class');
|
||||
$bAdvanced = utils::ReadParam('advanced', 0);
|
||||
$sEncoding = utils::ReadParam('encoding', 'UTF-8');
|
||||
$sDateTimeFormat = utils::ReadParam('date_time_format', 'default');
|
||||
$sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', AttributeDateTime::GetFormat(), false, 'raw_data');
|
||||
|
||||
$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
|
||||
if (!empty($sSynchroScope))
|
||||
@@ -788,6 +797,8 @@ EOF
|
||||
$oPage->add('<input type="hidden" name="csvdata" value="'.htmlentities($sCSVData, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
$oPage->add('<input type="hidden" name="encoding" value="'.$sEncoding.'">');
|
||||
$oPage->add('<input type="hidden" name="synchro_scope" value="'.$sSynchroScope.'">');
|
||||
$oPage->add('<input type="hidden" name="date_time_format" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
$oPage->add('<input type="hidden" name="custom_date_time_format" value="'.htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
if (!empty($sSynchroScope))
|
||||
{
|
||||
foreach($aSynchroUpdate as $sKey => $value)
|
||||
@@ -1092,6 +1103,8 @@ EOF
|
||||
$bAdvanced = utils::ReadParam('advanced', 0);
|
||||
$aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
|
||||
$aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
|
||||
$sDateTimeFormat = utils::ReadParam('date_time_format', 'default');
|
||||
$sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', AttributeDateTime::GetFormat(), false, 'raw_data');
|
||||
|
||||
// Create a truncated version of the data used for the fast preview
|
||||
// Take about 20 lines of data... knowing that some lines may contain carriage returns
|
||||
@@ -1134,7 +1147,7 @@ EOF
|
||||
|
||||
$oPage->add('<h2>'.Dict::S('UI:Title:CSVImportStep2').'</h2>');
|
||||
$oPage->add('<div class="wizContainer">');
|
||||
$oPage->add('<table><tr><td style="vertical-align:top;padding-right:50px;">');
|
||||
$oPage->add('<table><tr><td style="vertical-align:top;padding-right:30px;">');
|
||||
$oPage->add('<form enctype="multipart/form-data" id="wizForm" method="post" id="csv_options">');
|
||||
$oPage->add('<h3>'.Dict::S('UI:CSVImport:SeparatorCharacter').'</h3>');
|
||||
$oPage->add('<p><input type="radio" name="separator" value="," onClick="DoPreview()"'.IsChecked($sSeparator, ',').'/> '.Dict::S('UI:CSVImport:SeparatorComma+').'<br/>');
|
||||
@@ -1142,16 +1155,20 @@ EOF
|
||||
$oPage->add('<input type="radio" name="separator" value="tab" onClick="DoPreview()"'.IsChecked($sSeparator, "\t").'/> '.Dict::S('UI:CSVImport:SeparatorTab+').'<br/>');
|
||||
$oPage->add('<input type="radio" name="separator" value="other" onClick="DoPreview()"'.IsChecked($sOtherSeparator, '', true).'/> '.Dict::S('UI:CSVImport:SeparatorOther').' <input type="text" size="3" maxlength="1" name="other_separator" id="other_separator" value="'.$sOtherSeparator.'" onClick="DoPreview()"/>');
|
||||
$oPage->add('</p>');
|
||||
$oPage->add('</td><td style="vertical-align:top;padding-right:50px;">');
|
||||
$oPage->add('</td><td style="vertical-align:top;padding-right:30px;">');
|
||||
$oPage->add('<h3>'.Dict::S('UI:CSVImport:TextQualifierCharacter').'</h3>');
|
||||
$oPage->add('<p><input type="radio" name="text_qualifier" value=""" onClick="DoPreview()"'.IsChecked($sTextQualifier, '"').'/> '.Dict::S('UI:CSVImport:QualifierDoubleQuote+').'<br/>');
|
||||
$oPage->add('<input type="radio" name="text_qualifier" value="'" onClick="DoPreview()"'.IsChecked($sTextQualifier, "'").'/> '.Dict::S('UI:CSVImport:QualifierSimpleQuote+').'<br/>');
|
||||
$oPage->add('<input type="radio" name="text_qualifier" value="other" onClick="DoPreview()"'.IsChecked($sOtherTextQualifier, '', true).'/> '.Dict::S('UI:CSVImport:QualifierOther').' <input type="text" size="3" maxlength="1" name="other_qualifier" value="'.htmlentities($sOtherTextQualifier, ENT_QUOTES, 'UTF-8').'" onChange="DoPreview()"/>');
|
||||
$oPage->add('</p>');
|
||||
$oPage->add('</td><td style="vertical-align:top;">');
|
||||
$oPage->add('</td><td style="vertical-align:top;padding-right:30px;">');
|
||||
$oPage->add('<h3>'.Dict::S('UI:CSVImport:CommentsAndHeader').'</h3>');
|
||||
$oPage->add('<p><input type="checkbox" name="header_line" id="box_header" value="1" onClick="DoPreview()"'.IsChecked($bHeaderLine, 1).'/> '.Dict::S('UI:CSVImport:TreatFirstLineAsHeader').'<p>');
|
||||
$oPage->add('<p><input type="checkbox" name="box_skiplines" value="1" id="box_skiplines" onClick="DoPreview()"'.IsChecked($bBoxSkipLines, 1).'/> '.Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', '<input type="text" size=2 name="nb_skipped_lines" id="nb_skipped_lines" onChange="DoPreview()" value="'.$iSkippedLines.'">').'<p>');
|
||||
$oPage->add('</td><td style="vertical-align:top;">');
|
||||
$oPage->add('<h3>'.Dict::S('UI:CSVImport:DateAndTimeFormats').'</h3>');
|
||||
$oPage->add('<p><input type="radio" name="date_time_format" id="radio_date_time_std" value="default"'.IsChecked($sDateTimeFormat, 'default').'/> '.Dict::Format('UI:CSVImport:DefaultDateTimeFormat_Format_Example', htmlentities(AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8'), date(AttributeDateTime::GetFormat())).'<p>');
|
||||
$oPage->add('<p><input type="radio" name="date_time_format" id="radio_date_time_custom" value="custom"'.IsChecked($sDateTimeFormat, 'custom').'/> '.Dict::Format('UI:CSVImport:CustomDateTimeFormat', '<input type="text" size="15" name="custom_date_time_format" id="custom_date_time_format" title="" value="'.htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8').'">').'<p>');
|
||||
$oPage->add('</td></tr></table>');
|
||||
$oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="'.htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
$oPage->add('<input type="hidden" name="csvdata" id="csvdata" value="'.htmlentities($sUTF8Data, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
@@ -1240,7 +1257,13 @@ EOF
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$oPage->add_ready_script('DoPreview();');
|
||||
$sJSTooltip = json_encode('<div class="date_format_tooltip">'.Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip').'</div>');
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
DoPreview();
|
||||
$('#custom_date_time_format').tooltip({content: function() { return $sJSTooltip; } });
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1274,6 +1297,9 @@ EOF
|
||||
$sClassName = utils::ReadParam('class_name', '');
|
||||
$bAdvanced = utils::ReadParam('advanced', 0);
|
||||
$sEncoding = utils::ReadParam('encoding', '');
|
||||
$sDateTimeFormat = utils::ReadParam('date_time_format', 'default');
|
||||
$sCustomDateTimeFormat = utils::ReadParam('custom_date_time_format', AttributeDateTime::GetFormat(), false, 'raw_data');
|
||||
|
||||
if ($sEncoding == '')
|
||||
{
|
||||
$sEncoding = MetaModel::GetConfig()->Get('csv_file_default_charset');
|
||||
@@ -1335,6 +1361,8 @@ EOF
|
||||
'<input type="hidden" name="operation" value="csv_data"/>'.
|
||||
'<input type="hidden" name="separator" value="'.htmlentities($sSeparator, ENT_QUOTES, 'UTF-8').'"/>'.
|
||||
'<input type="hidden" name="text_qualifier" value="'.htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8').'"/>'.
|
||||
'<input type="hidden" name="date_time_format" value="'.htmlentities($sDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>'.
|
||||
'<input type="hidden" name="custom_date_time_format" value="'.htmlentities($sCustomDateTimeFormat, ENT_QUOTES, 'UTF-8').'"/>'.
|
||||
'<input type="hidden" name="header_line" value="'.$bHeaderLine.'"/>'.
|
||||
'<input type="hidden" name="nb_skipped_lines" value="'.utils::ReadParam('nb_skipped_lines', '0').'"/>'.
|
||||
'<input type="hidden" name="box_skiplines" value="'.utils::ReadParam('box_skiplines', '0').'"/>'.
|
||||
|
||||
@@ -1798,4 +1798,91 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.</pre>]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product>jQuery Timepicker addon</product>
|
||||
<author>Trent Richardson</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[<pre>
|
||||
Copyright (c) 2009 Trent Richardson, http://trentrichardson.com/Impromptu/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</pre>]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product>D3 js</product>
|
||||
<author>Mike Bostock</author>
|
||||
<license_type>BSD</license_type>
|
||||
<text><![CDATA[<pre>
|
||||
Copyright (c) 2010-2016, Michael Bostock
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The name Michael Bostock may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
</pre>]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product>C3 js</product>
|
||||
<author>Masayuki Tanaka</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[<pre>
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Masayuki Tanaka
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</pre>]]></text>
|
||||
</license>
|
||||
</licenses>
|
||||
@@ -97,7 +97,7 @@ $aPageParams = array
|
||||
'mandatory' => false,
|
||||
'modes' => 'http,cli',
|
||||
'default' => '',
|
||||
'description' => 'Input date format (used both for dates and datetimes) - Examples: %Y-%m-%d, %d/%m/%Y (Europe) - no transformation is applied if the argument is omitted',
|
||||
'description' => 'Input date format (used both for dates and datetimes) - Examples: Y-m-d, d/m/Y (Europe) - no transformation is applied if the argument is omitted. (note: old format specification using %Y %m %d is also supported for backward compatibility)',
|
||||
),
|
||||
'separator' => array
|
||||
(
|
||||
@@ -217,10 +217,10 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter)
|
||||
function ChangeDateFormat($sProposedDate, $sDateFormat)
|
||||
{
|
||||
// Make sure this is a valid MySQL datetime
|
||||
$iTime = utils::StringToTime($sProposedDate, $sDateFormat);
|
||||
if ($iTime !== false)
|
||||
$oDate = DateTime::createFromFormat($sDateFormat, $sProposedDate);
|
||||
if ($oDate !== false)
|
||||
{
|
||||
$sDate = date('Y-m-d H:i:s', $iTime);
|
||||
$sDate = $oDate->format(AttributeDateTime::GetInternalFormat());
|
||||
return $sDate;
|
||||
}
|
||||
else
|
||||
@@ -311,6 +311,10 @@ try
|
||||
$sQualifier = ReadParam($oP, 'qualifier', 'raw_data');
|
||||
$sCharSet = ReadParam($oP, 'charset', 'raw_data');
|
||||
$sDateFormat = ReadParam($oP, 'date_format', 'raw_data');
|
||||
if (strpos($sDateFormat, '%') !== false)
|
||||
{
|
||||
$sDateFormat = utils::DateTimeFormatToPHP($sDateFormat);
|
||||
}
|
||||
$sOutput = ReadParam($oP, 'output');
|
||||
// $sReportLevel = ReadParam($oP, 'reportlevel');
|
||||
$sSimulate = ReadParam($oP, 'simulate');
|
||||
|
||||
@@ -1862,7 +1862,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
{
|
||||
$oStatLog->Inc($sStatsCode.'_updated');
|
||||
}
|
||||
$this->Set('info_last_modified', date('Y-m-d H:i:s'));
|
||||
$this->Set('info_last_modified', date(AttributeDateTime::GetSQLFormat()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1912,7 +1912,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
$this->Set('status_dest_creator', true);
|
||||
$this->Set('status_last_error', '');
|
||||
$this->Set('status', 'synchronized');
|
||||
$this->Set('info_creation_date', date('Y-m-d H:i:s'));
|
||||
$this->Set('info_creation_date', date(AttributeDateTime::GetSQLFormat()));
|
||||
$bCreated = true;
|
||||
|
||||
$oStatLog->AddTrace("Created (".implode(', ', $aValueTrace).")", $this);
|
||||
@@ -1950,7 +1950,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
}
|
||||
$oDestObj->Set($sAttCode, $value);
|
||||
}
|
||||
$this->Set('info_last_modified', date('Y-m-d H:i:s'));
|
||||
$this->Set('info_last_modified', date(AttributeDateTime::GetSQLFormat()));
|
||||
$oDestObj->DBUpdateTracked($oChange);
|
||||
$oStatLog->AddTrace("Replica marked as obsolete", $this);
|
||||
$oStatLog->Inc('stats_nb_obj_obsoleted');
|
||||
|
||||
@@ -4896,6 +4896,82 @@ class TestLinkSetRecording_1NAdd_Remove extends TestBizModel
|
||||
}
|
||||
}
|
||||
|
||||
class TestDateTimeFormats extends TestBizModel
|
||||
{
|
||||
static public function GetName() {return 'Check Date & Time formating and parsing';}
|
||||
static public function GetDescription() {return 'Check the formating and parsing of dates for various formats';}
|
||||
public function DoExecute()
|
||||
{
|
||||
$bRet = true;
|
||||
$aTestFormats = array(
|
||||
'French (short)' => 'd/m/Y H:i:s',
|
||||
'French (short - no seconds)' => 'd/m/Y H:i',
|
||||
'French (long)' => 'd/m/Y H\\h i\\m\\i\\n s\\s',
|
||||
'English US' => 'm/d/Y H:i:s',
|
||||
'English US (12 hours)' => 'm/d/Y h:i:s a',
|
||||
'English US (12 hours, short)' => 'n/j/Y g:i:s a',
|
||||
'English UK' => 'd/m/Y H:i:s',
|
||||
'German' => 'd.m.Y H:i:s',
|
||||
'SQL' => 'Y-m-d H:i:s',
|
||||
);
|
||||
// Valid date and times, all tests should pass
|
||||
$aTestDates = array('2015-01-01 00:00:00', '2015-12-31 23:59:00', '2016-01-01 08:21:00', '2016-02-28 12:30:00', '2016-02-29 16:47:00', /*'2016-02-29 14:30:17'*/);
|
||||
foreach($aTestFormats as $sDesc => $sFormat)
|
||||
{
|
||||
$this->ReportSuccess("Test of the '$sDesc' format: '$sFormat':");
|
||||
AttributeDateTime::SetFormat($sFormat);
|
||||
foreach($aTestDates as $sTestDate)
|
||||
{
|
||||
$oDate = new DateTime($sTestDate);
|
||||
$sFormattedDate = AttributeDateTime::Format($oDate, AttributeDateTime::GetFormat());
|
||||
$sParsedDate = AttributeDateTime::Parse($sFormattedDate, AttributeDateTime::GetFormat());
|
||||
$sPattern = AttributeDateTime::GetRegExpr();
|
||||
$bParseOk = ($sParsedDate == $sTestDate);
|
||||
if (!$bParseOk)
|
||||
{
|
||||
$this->ReportError('Parsed ('.$sFormattedDate.') date different from initial date (difference of '.((int)$oParsedDate->format('U')- (int)$oDate->format('U')).'s)');
|
||||
$bRet = false;
|
||||
}
|
||||
$bValidateOk = preg_match('/'.$sPattern.'/', $sFormattedDate);
|
||||
if (!$bValidateOk)
|
||||
{
|
||||
$this->ReportError('Formatted date ('.$sFormattedDate.') does not match the validation pattern ('.$sPattern.')');
|
||||
$bRet = false;
|
||||
}
|
||||
|
||||
$this->ReportSuccess("Formatted date: $sFormattedDate - Parsing: ".($bParseOk ? 'Ok' : '<b>KO</b>')." - Validation: ".($bValidateOk ? 'Ok' : '<b>KO</b>'));
|
||||
}
|
||||
echo "</p>\n";
|
||||
}
|
||||
|
||||
// Invalid date & time strings, all regexpr validation should fail
|
||||
$aInvalidTestDates = array(
|
||||
'SQL' => array('2015-13-01 00:00:00', '2015-12-51 23:59:00', '2016-01-01 +08:21:00', '2016-02-28 24:30:00', '2016-02-29 16:67:88'),
|
||||
'French (short)' => array('01/01/20150 00:00:00', '01/01/20150 00:00:00', '01/13/2015 00:00:00', '01/01/2015 40:00:00', '01/01/2015 00:99:00'),
|
||||
'English US (12 hours)' => array('13/01/2015 12:00:00 am', '12/33/2015 12:00:00 am', '12/23/215 12:00:00 am', '05/04/2016 16:00:00 am', '05/04/2016 10:00:00 ap'),
|
||||
);
|
||||
|
||||
foreach($aInvalidTestDates as $sFormatName => $aDatesToParse)
|
||||
{
|
||||
$sFormat = $aTestFormats[$sFormatName];
|
||||
AttributeDateTime::SetFormat($sFormat);
|
||||
$this->ReportSuccess("Test of the '$sFormatName' format: '$sFormat':");
|
||||
foreach($aDatesToParse as $sDate)
|
||||
{
|
||||
$sPattern = AttributeDateTime::GetRegExpr();
|
||||
$bValidateOk = preg_match('/'.$sPattern.'/', $sDate);
|
||||
if ($bValidateOk)
|
||||
{
|
||||
$this->ReportError('Formatted date ('.$sFormattedDate.') matches the validation pattern ('.$sPattern.') whereas it should not!');
|
||||
$bRet = false;
|
||||
}
|
||||
$this->ReportSuccess("Formatted date: $sDate - Validation: ".($bValidateOk ? '<b>KO</n>' : 'rejected, Ok.'));
|
||||
}
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
}
|
||||
|
||||
class TestExecActions extends TestBizModel
|
||||
{
|
||||
static public function GetName()
|
||||
|
||||
@@ -96,7 +96,7 @@ $aPageParams = array
|
||||
'mandatory' => false,
|
||||
'modes' => 'http,cli',
|
||||
'default' => '',
|
||||
'description' => 'Input date format (used both for dates and datetimes) - Examples: %Y-%m-%d, %d/%m/%Y (Europe) - no transformation is applied if the argument is omitted',
|
||||
'description' => 'Input date format (used both for dates and datetimes) - Examples: Y-m-d H:i:s, d/m/Y H:i:s (Europe) - no transformation is applied if the argument is omitted. (note: old format specification using %Y %m %d is also supported for backward compatibility)',
|
||||
),
|
||||
'separator' => array
|
||||
(
|
||||
@@ -287,6 +287,10 @@ try
|
||||
$sQualifier = ReadParam($oP, 'qualifier', 'raw_data');
|
||||
$sCharSet = ReadParam($oP, 'charset', 'raw_data');
|
||||
$sDateFormat = ReadParam($oP, 'date_format', 'raw_data');
|
||||
if (strpos($sDateFormat, '%') !== false)
|
||||
{
|
||||
$sDateFormat = utils::DateTimeFormatToPHP($sDateFormat);
|
||||
}
|
||||
$sOutput = ReadParam($oP, 'output', 'string');
|
||||
$sReconcKeys = ReadParam($oP, 'reconciliationkeys', 'raw_data');
|
||||
$sSimulate = ReadParam($oP, 'simulate');
|
||||
|
||||
Reference in New Issue
Block a user