Commit bc25beec authored by Mark Webster's avatar Mark Webster Committed by Robert Lyon
Browse files

Bug 1771362: Fix timezone issues.

Adds timezone dropdown the site settings. If no timezone selected
it uses site settings country to determine correct timezone and sets
that in the database.
PHP and DB session timezones will then assume this setting for all times.

This makes setting $cfg->dbtimezone obsolete - there is a warning to
admins to update their timezone setting on admin dashboard.

Limitations:
- A timezone or country MUST be selected in site options.

- Will not correct existing incorrect times, as no timezone info was
stored in the DB for dates/times, so it's impossible to determine what timezone
was used when saving.

- Changing the timezone will not adjust the display of existing times, for the
same reason.

behatnotneeded

Change-Id: I34c64cd51ece6758e76dd8c37007dcb316005845
parent ecfd138b
......@@ -29,6 +29,7 @@ unset($themeoptions['custom']); // Only available for institution configurable t
$searchpluginoptions = get_search_plugins();
$countries = getoptions_country();
$timezones = getoptions_timezone();
$notificationelements = get_notification_settings_elements(null, true);
......@@ -77,6 +78,15 @@ $siteoptionform = array(
'help' => true,
'disabled' => in_array('country', $OVERRIDDEN),
),
'timezone' => array(
'type' => 'select',
'title' => get_string('timezone', 'admin'),
'description' => get_string('sitetimezonedescription', 'admin'),
'defaultvalue' => get_config('timezone'),
'options' => array('' => get_string('notimezoneselected', 'admin')) + $timezones,
'help' => true,
'disabled' => in_array('timezone', $OVERRIDDEN),
),
'theme' => array(
'type' => 'select',
'title' => get_string('theme'),
......@@ -816,7 +826,7 @@ function siteoptions_submit(Pieform $form, $values) {
'mathjax', 'institutionexpirynotification', 'institutionautosuspend', 'requireregistrationconfirm',
'institutionstrictprivacy',
'showselfsearchsideblock', 'nousernames', 'searchplugin', 'showtagssideblock',
'tagssideblockmaxtags', 'country', 'userscanchooseviewthemes', 'internalnotificationexpire',
'tagssideblockmaxtags', 'country', 'timezone', 'userscanchooseviewthemes', 'internalnotificationexpire',
'remoteavatars', 'userscanhiderealnames', 'antispam', 'spamhaus', 'surbl', 'anonymouscomments', 'passwordpolicy',
'recaptchaonregisterform', 'recaptchapublickey', 'recaptchaprivatekey', 'loggedinprofileviewaccess', 'disableexternalresources',
'proxyaddress', 'proxyauthmodel', 'proxyauthcredentials', 'smtphosts', 'smtpport', 'smtpuser', 'smtppass', 'smtpsecure',
......
......@@ -500,7 +500,9 @@ $string['reviewsselfdeletiondescription'] = 'An institution administrator must a
$string['mathjax'] = 'Enable MathJax';
$string['mathjaxdescription'] = 'MathJax renders LaTeX markup into properly formatted math and science equations on portfolio pages.';
$string['mathjaxconfig'] = 'MathJax configuration';
$string['timezone'] = 'Timezone';
$string['sitetimezonedescription'] = 'The default timezone for the site. If not selected one will be chosen based on country, but this can be innaccurate if the counrty has multiple timezones.';
$string['notimezoneselected'] = 'No Timezone Selected';
// Site content
$string['about'] = 'About';
$string['discardpageedits'] = 'Discard your changes to this page?';
......
......@@ -151,3 +151,4 @@ $string['nophpextension'] = 'The PHP extension "%s" is not enabled. Please enabl
$string['nomemcacheserversdefined'] = 'The session save handler "%s" has no related servers defined. Please set the $cfg->memcacheservers value, e.g. "localhost:11211".';
$string['memcacheusememcached'] = 'The "memcache" session storage is obsolete. Please use "memcached".';
$string['siteoutofsyncfor'] = 'This site has database information newer than %s files indicate it should be.';
$string['updatesitetimezone'] = 'The timezone for the site now needs to be set via Configure site → Site options → Site settings. Please set it there and delete the $cfg->dbtimezone line from your config.php file.';
......@@ -617,14 +617,6 @@ $cfg->usersuniquebyusername = false;
*/
$cfg->dbprefix = '';
/**
* @global string $cfg->dbtimezone Sets the timezone for your database connection. This is only necessary if your
* database server has a different timezone than your web server (which is most likely to happen in cloud hosting).
* Consult your database's manual for legal values.
*/
// $cfg->dbtimezone = '+10:00';
// $cfg->dbtimezone = 'Europe/Rome';
/**
* @global bool $cfg->publicsearchallowed Activates the display of the search box for logged-out users
*/
......
......@@ -1544,12 +1544,45 @@ function configure_dbconnection() {
$db->SetTransactionMode('READ COMMITTED');
if (!empty($CFG->dbtimezone)) {
if (is_postgres()) {
$db->_Execute("SET SESSION TIME ZONE '{$CFG->dbtimezone}'");
// Bug 1771362: Set timezone for PHP and the DB to a user selected timezone or the country
// selected in site settings (if no timezone selected) to avoid innaccurate times being shown.
try {
$timezoners = $db->_Execute("SELECT value FROM " . db_table_name('config') . " WHERE field = 'timezone' LIMIT 1");
if (!$timezoners->fields || $timezoners->fields['value'] == "") {
$countryrs = $db->_Execute("SELECT value FROM " . db_table_name('config') . " WHERE field = 'country' LIMIT 1");
if ($countryrs->fields && $countryrs->fields['value'] != "") {
// Get the two letter country identifier.
$country = $countryrs->fields['value'];
// Country ID has to be uppercase or this won't work.
$timezone = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, strtoupper($country))[0];
if (!$timezoners->fields) {
$db->_Execute("INSERT INTO " . db_table_name('config') . " (field, value) VALUES ('timezone', '" . $timezone . "')");
}
else {
$db->_Execute("UPDATE " . db_table_name('config') . " SET value = '" . $timezone . "' WHERE field = 'timezone'");
}
}
}
else {
$timezone = $timezoners->fields['value'];
}
if (is_mysql()) {
$db->_Execute("SET time_zone='{$CFG->dbtimezone}'");
if (!empty($timezone)) {
date_default_timezone_set($timezone); // For PHP.
$timediff = date('P'); // MySQL doesn't always have the timezone table populated
// so we set it using the offset from UTC in hours.
if (is_postgres()) {
$db->_Execute("SET SESSION TIME ZONE '{$timezone}'");
}
if (is_mysql() && $timediff) {
$db->_Execute("SET time_zone='{$timediff}'");
}
}
}
catch (Exception $e) {
// Site probably not installed yet, but throw exception if it is.
if (get_config('installed')) {
throw new SQLException('Unable to set timezone for connection: ' . $e);
}
}
}
......
......@@ -1546,6 +1546,9 @@ function site_warnings() {
if ($tz_count == 0 || $tz_count == FALSE) {
$warnings[] = get_string('timezoneidentifierunusable', 'error');
}
if (get_config('dbtimezone')) {
$warnings[] = get_string('updatesitetimezone', 'error');
}
// Check for low security (i.e. not random enough) session IDs
if (version_compare(PHP_VERSION, '7.1.0') < 0 && (int)ini_get('session.entropy_length') < 16) {
......
......@@ -2162,6 +2162,25 @@ function getoptions_country() {
return $countries;
}
/**
* Returns an assoc array of timezones suitable for use with the "select" form
* element
*
* @return array Associative array of timezone => timezone
*/
function getoptions_timezone() {
static $timezones;
if (!empty($timezones)) {
return $timezones;
}
$zones = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
foreach ($zones as $z) {
$timezones[$z] = $z;
};
return $timezones;
}
/**
* Returns an HTML string with a help icon image that can be used on a page.
* When the icon is clicked, a dialog box will be shown with contextual help
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment