MDL-18375 calendar: removed usage of the calendar type in the usergetdate function

The usergetdate function is not only used to display dates, it is also passed
to the function make_timestamp. This means users using another calendar type
other than Gregorian will generate incorrect timestamps which may be saved in
the DB or used to populate the date_selector and date_time_selector elements.
For example, when creating an assignment using another calendar type other
than Gregorian, the mod_form.php file calls $this->apply_admin_defaults()
which uses the function usergetmidnight to set the "Allow submissions from"
date to today's date and the "Due date" field to 7 days in the future. The
usergetmidnight function calls usergetdate which is then passed to
make_timestamp. Since the usergetdate function was using the calendar
type's timestamp_to_date_array function the date being passed to
make_timestamp was not in Gregorian. So, when using the hijri calendar the
year 1434 was being passed which was generating a large negative number as
the timestamp which was then used to populate the date fields.
This commit is contained in:
Mark Nelson 2013-08-23 14:14:50 +08:00
parent 6eafa4ddba
commit deed22ea39
6 changed files with 80 additions and 78 deletions

View File

@ -177,16 +177,12 @@ class core_calendar_type_testcase extends advanced_testcase {
private function core_functions_test($type) {
$this->set_calendar_type($type);
$class = "\\calendartype_$type\\structure";
$calendar = new $class();
// Get the calendar.
$calendar = \core_calendar\type_factory::get_calendar_instance();
// Test the userdate function.
$this->assertEquals($calendar->timestamp_to_date_string($this->user->timecreated, '', 99, true, true),
userdate($this->user->timecreated));
// Test the usergetdate function.
$this->assertEquals($calendar->timestamp_to_date_array($this->user->timecreated, '', 99, true, true),
usergetdate($this->user->timecreated));
}
/**
@ -220,7 +216,10 @@ class core_calendar_type_testcase extends advanced_testcase {
private function convert_unixtime_to_dateselector_test($type, $date) {
$this->set_calendar_type($type);
$usergetdate = usergetdate($date['timestamp'], 0.0);
// Get the calendar.
$calendar = \core_calendar\type_factory::get_calendar_instance();
$usergetdate = $calendar->timestamp_to_date_array($date['timestamp'], 0.0);
$comparedate = array(
'minute' => $usergetdate['minutes'],
'hour' => $usergetdate['hours'],

View File

@ -177,50 +177,7 @@ class structure extends type_base {
* @return array an array that represents the date in user time
*/
public function timestamp_to_date_array($time, $timezone) {
// Save input timezone, required for dst offset check.
$passedtimezone = $timezone;
$timezone = get_user_timezone_offset($timezone);
if (abs($timezone) > 13) { // Server time.
return getdate($time);
}
// Add daylight saving offset for string timezones only, as we can't get dst for
// float values. if timezone is 99 (user default timezone), then try update dst.
if ($passedtimezone == 99 || !is_numeric($passedtimezone)) {
$time += dst_offset_on($time, $passedtimezone);
}
$time += intval((float)$timezone * HOURSECS);
$datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time);
// Be careful to ensure the returned array matches that produced by getdate() above.
list (
$getdate['month'],
$getdate['weekday'],
$getdate['yday'],
$getdate['year'],
$getdate['mon'],
$getdate['wday'],
$getdate['mday'],
$getdate['hours'],
$getdate['minutes'],
$getdate['seconds']
) = explode('_', $datestring);
// Set correct datatype to match with getdate().
$getdate['seconds'] = (int) $getdate['seconds'];
$getdate['yday'] = (int) $getdate['yday'] - 1;
$getdate['year'] = (int) $getdate['year'];
$getdate['mon'] = (int) $getdate['mon'];
$getdate['wday'] = (int) $getdate['wday'];
$getdate['mday'] = (int) $getdate['mday'];
$getdate['hours'] = (int) $getdate['hours'];
$getdate['minutes'] = (int) $getdate['minutes'];
return $getdate;
return usergetdate($time, $timezone);
}
/**

View File

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2013070300; // The current plugin version (Date: YYYYMMDDXX).
$plugin->version = 2013082300; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2012120300; // Requires this Moodle version.
$plugin->component = 'calendartype_gregorian'; // Full name of the plugin (used for diagnostics).

View File

@ -153,12 +153,12 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group {
function onQuickFormEvent($event, $arg, &$caller) {
switch ($event) {
case 'updateValue':
// constant values override both default and submitted ones
// default values are overriden by submitted
// Constant values override both default and submitted ones
// default values are overriden by submitted.
$value = $this->_findValue($caller->_constantValues);
if (null === $value) {
// if no boxes were checked, then there is no value in the array
// yet we don't want to display default value in this case
// If no boxes were checked, then there is no value in the array
// yet we don't want to display default value in this case.
if ($caller->isSubmitted()) {
$value = $this->_findValue($caller->_submitValues);
} else {
@ -170,19 +170,20 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group {
$value = time();
}
if (!is_array($value)) {
$currentdate = usergetdate($value, $this->_options['timezone']);
$calendartype = \core_calendar\type_factory::get_calendar_instance();
$currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
$value = array(
'day' => $currentdate['mday'],
'month' => $currentdate['mon'],
'year' => $currentdate['year']);
// If optional, default to off, unless a date was provided
if($this->_options['optional']) {
// If optional, default to off, unless a date was provided.
if ($this->_options['optional']) {
$value['enabled'] = $requestvalue != 0;
}
} else {
$value['enabled'] = isset($value['enabled']);
}
if (null !== $value){
if (null !== $value) {
$this->setValue($value);
}
break;

View File

@ -168,12 +168,12 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group {
function onQuickFormEvent($event, $arg, &$caller) {
switch ($event) {
case 'updateValue':
// constant values override both default and submitted ones
// default values are overriden by submitted
// Constant values override both default and submitted ones
// default values are overriden by submitted.
$value = $this->_findValue($caller->_constantValues);
if (null === $value) {
// if no boxes were checked, then there is no value in the array
// yet we don't want to display default value in this case
// If no boxes were checked, then there is no value in the array
// yet we don't want to display default value in this case.
if ($caller->isSubmitted()) {
$value = $this->_findValue($caller->_submitValues);
} else {
@ -188,7 +188,8 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group {
}
}
if (!is_array($value)) {
$currentdate = usergetdate($value, $this->_options['timezone']);
$calendartype = \core_calendar\type_factory::get_calendar_instance();
$currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
// Round minutes to the previous multiple of step.
$currentdate['minutes'] -= $currentdate['minutes'] % $this->_options['step'];
$value = array(
@ -197,19 +198,19 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group {
'day' => $currentdate['mday'],
'month' => $currentdate['mon'],
'year' => $currentdate['year']);
// If optional, default to off, unless a date was provided
if($this->_options['optional']) {
// If optional, default to off, unless a date was provided.
if ($this->_options['optional']) {
$value['enabled'] = $requestvalue != 0;
}
} else {
$value['enabled'] = isset($value['enabled']);
}
if (null !== $value){
if (null !== $value) {
$this->setValue($value);
}
break;
case 'createElement':
if($arg[2]['optional']) {
if ($arg[2]['optional']) {
// When using the function addElement, rather than createElement, we still
// enter this case, making this check necessary.
if ($this->_usedcreateelement) {

View File

@ -2191,19 +2191,63 @@ function date_format_string($date, $format, $tz = 99) {
}
/**
* Given a $time timestamp in GMT (seconds since epoch), returns an array that represents
* the date in user time.
* Given a $time timestamp in GMT (seconds since epoch),
* returns an array that represents the date in user time
*
* @package core
* @category time
* @param int $time timestamp in GMT
* @param float|int|string $timezone the timezone to use to calculate the time
* {@link http://docs.moodle.org/dev/Time_API#Timezone}
* @return array an array that represents the date in user time
* @uses HOURSECS
* @param int $time Timestamp in GMT
* @param float|int|string $timezone offset's time with timezone, if float and not 99, then no
* dst offset is applied {@link http://docs.moodle.org/dev/Time_API#Timezone}
* @return array An array that represents the date in user time
*/
function usergetdate($time, $timezone = 99) {
$calendartype = \core_calendar\type_factory::get_calendar_instance();
return $calendartype->timestamp_to_date_array($time, $timezone);
function usergetdate($time, $timezone=99) {
// Save input timezone, required for dst offset check.
$passedtimezone = $timezone;
$timezone = get_user_timezone_offset($timezone);
if (abs($timezone) > 13) {
// Server time.
return getdate($time);
}
// Add daylight saving offset for string timezones only, as we can't get dst for
// float values. if timezone is 99 (user default timezone), then try update dst.
if ($passedtimezone == 99 || !is_numeric($passedtimezone)) {
$time += dst_offset_on($time, $passedtimezone);
}
$time += intval((float)$timezone * HOURSECS);
$datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time);
// Be careful to ensure the returned array matches that produced by getdate() above.
list(
$getdate['month'],
$getdate['weekday'],
$getdate['yday'],
$getdate['year'],
$getdate['mon'],
$getdate['wday'],
$getdate['mday'],
$getdate['hours'],
$getdate['minutes'],
$getdate['seconds']
) = explode('_', $datestring);
// Set correct datatype to match with getdate().
$getdate['seconds'] = (int)$getdate['seconds'];
$getdate['yday'] = (int)$getdate['yday'] - 1; // The function gmstrftime returns 0 through 365.
$getdate['year'] = (int)$getdate['year'];
$getdate['mon'] = (int)$getdate['mon'];
$getdate['wday'] = (int)$getdate['wday'];
$getdate['mday'] = (int)$getdate['mday'];
$getdate['hours'] = (int)$getdate['hours'];
$getdate['minutes'] = (int)$getdate['minutes'];
return $getdate;
}
/**