Skip to content

Commit

Permalink
Merge branch 'feature/timezone-detection-6078'
Browse files Browse the repository at this point in the history
resolves #6078
  • Loading branch information
mxhash committed Sep 5, 2014
2 parents 0b53f30 + 7b73adb commit 975985d
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 13 deletions.
17 changes: 15 additions & 2 deletions application/forms/Preference/GeneralForm.php
Expand Up @@ -5,6 +5,7 @@
namespace Icinga\Form\Preference;

use DateTimeZone;
use Icinga\Util\TimezoneDetect;
use Zend_Config;
use Zend_Form_Element_Text;
use Zend_Form_Element_Select;
Expand Down Expand Up @@ -69,13 +70,22 @@ private function addLanguageSelection(Zend_Config $cfg)
*/
private function addTimezoneSelection(Zend_Config $cfg)
{
$prefs = $this->getUserPreferences();
$useGlobalTimezone = $this->getRequest()->getParam('default_timezone', !$prefs->has('app.timezone'));
$detect = new TimezoneDetect();

$tzList = array();
foreach (DateTimeZone::listIdentifiers() as $tz) {
$tzList[$tz] = $tz;
}

$helptext = 'Use the following timezone for dates and times';
$prefs = $this->getUserPreferences();
$useGlobalTimezone = $this->getRequest()->getParam('default_timezone', !$prefs->has('app.timezone'));

if ($useGlobalTimezone && $detect->success() === true) {
$helptext .= '<br />' . t('Currently your time was detected to be')
. ': '
. '<strong>' . $detect->getTimezoneName() . '</strong>';
}

$selectTimezone = new Zend_Form_Element_Select(
array(
Expand All @@ -87,6 +97,7 @@ private function addTimezoneSelection(Zend_Config $cfg)
'value' => $prefs->get('app.timezone', $cfg->get('timezone', date_default_timezone_get()))
)
);

$this->addElement(
'checkbox',
'default_timezone',
Expand All @@ -99,7 +110,9 @@ private function addTimezoneSelection(Zend_Config $cfg)
if ($useGlobalTimezone) {
$selectTimezone->setAttrib('disabled', 1);
}

$this->addElement($selectTimezone);

$this->enableAutoSubmit(array('default_timezone'));
}

Expand Down
8 changes: 5 additions & 3 deletions library/Icinga/Application/Web.php
Expand Up @@ -10,6 +10,7 @@
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotReadableError;
use Icinga\Logger\Logger;
use Icinga\Util\TimezoneDetect;
use Icinga\Web\Request;
use Icinga\Web\Response;
use Icinga\Web\View;
Expand Down Expand Up @@ -273,10 +274,11 @@ private function setupPagination()
*/
protected function setupTimezone()
{
$userTimezone = null;

if ($this->user !== null && $this->user->getPreferences() !== null) {
$userTimezone = $this->user->getPreferences()->get('app.timezone');
} else {
$userTimezone = null;
$detect = new TimezoneDetect();
$userTimezone = $this->user->getPreferences()->get('app.timezone', $detect->getTimezoneName());
}

try {
Expand Down
108 changes: 108 additions & 0 deletions library/Icinga/Util/TimezoneDetect.php
@@ -0,0 +1,108 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}

namespace Icinga\Util;

use Icinga\Application\Platform;

/**
* Retrieve timezone information from cookie
*/
class TimezoneDetect
{
/**
* If detection was successful
*
* @var bool
*/
private static $success;

/**
* Timezone offset in minutes
*
* @var int
*/
private static $offset = 0;

/**
* @var string
*/
private static $timezoneName;

/**
* Cookie name
*
* @var string
*/
public static $cookieName = 'icingaweb2-tzo';

/**
* Timezone name
*
* @var string
*/
private static $timezone;

/**
* Create new object and try to identify the timezone
*/
public function __construct()
{
if (self::$success !== null) {
return;
}

if (Platform::isCli() === false && array_key_exists(self::$cookieName, $_COOKIE)) {
list($offset, $dst) = explode(',', $_COOKIE[self::$cookieName]);
$timezoneName = timezone_name_from_abbr('', (int)$offset, (int)$dst);

self::$success = (bool)$timezoneName;

if (self::$success === true) {
self::$offset = $offset;
self::$timezoneName = $timezoneName;
}
}
}

/**
* Get offset
*
* @return int
*/
public function getOffset()
{
return self::$offset;
}

/**
* Get timezone name
*
* @return string
*/
public function getTimezoneName()
{
return self::$timezoneName;
}

/**
* True on success
*
* @return bool
*/
public function success()
{
return self::$success;
}

/**
* Reset object
*/
public function reset()
{
self::$success = null;
self::$timezoneName = null;
self::$offset = 0;
}
}
1 change: 1 addition & 0 deletions library/Icinga/Web/JavaScript.php
Expand Up @@ -21,6 +21,7 @@ class JavaScript
'js/icinga/events.js',
'js/icinga/history.js',
'js/icinga/module.js',
'js/icinga/timezone.js',
);

protected static $vendorFiles = array(
Expand Down
19 changes: 11 additions & 8 deletions public/js/icinga.js
Expand Up @@ -82,14 +82,16 @@
return false;
}

this.utils = new Icinga.Utils(this);
this.logger = new Icinga.Logger(this);
this.timer = new Icinga.Timer(this);
this.ui = new Icinga.UI(this);
this.loader = new Icinga.Loader(this);
this.events = new Icinga.Events(this);
this.history = new Icinga.History(this);

this.timezone = new Icinga.Timezone();
this.utils = new Icinga.Utils(this);
this.logger = new Icinga.Logger(this);
this.timer = new Icinga.Timer(this);
this.ui = new Icinga.UI(this);
this.loader = new Icinga.Loader(this);
this.events = new Icinga.Events(this);
this.history = new Icinga.History(this);

this.timezone.initialize();
this.timer.initialize();
this.events.initialize();
this.history.initialize();
Expand Down Expand Up @@ -147,6 +149,7 @@
module.destroy();
});

this.timezone.destroy();
this.timer.destroy();
this.events.destroy();
this.loader.destroy();
Expand Down
117 changes: 117 additions & 0 deletions public/js/icinga/timezone.js
@@ -0,0 +1,117 @@
(function(Icinga, $) {

'use strict';

/**
* Get the maximum timezone offset
*
* @returns {Number}
*/
Date.prototype.getStdTimezoneOffset = function() {
if (Date.maxTimezoneOffset !== undefined) {
return Date.maxTimezoneOffset;
}

var year = new Date().getYear();
var previousOffset;

for (var i=0; i<12; i++) {
var d = new Date(year, i, 1);
if (previousOffset !== undefined) {
previousOffset = Math.max(previousOffset, d.getTimezoneOffset());
} else {
previousOffset = d.getTimezoneOffset();
}
}

Date.maxTimezoneOffset = previousOffset;

return Date.maxTimezoneOffset;
};

/**
* Test for daylight saving time zone
*
* @returns {boolean}
*/
Date.prototype.isDst = function() {
return (this.getStdTimezoneOffset() === this.getTimezoneOffset()) ? false : true;
};

/**
* Write timezone information into a cookie
*
* @constructor
*/
Icinga.Timezone = function() {
this.cookieName = 'icingaweb2-tzo';
};

Icinga.Timezone.prototype = {
/**
* Initialize interface method
*/
initialize: function () {
this.writeTimezone();
},

destroy: function() {
// PASS
},

/**
* Write timezone information into cookie
*/
writeTimezone: function() {
var date = new Date();
var timezoneOffset = (date.getTimezoneOffset()*60) * -1;
var dst = date.isDst();

if (this.readCookie(this.cookieName)) {
return;
}

this.writeCookie(this.cookieName, timezoneOffset + ',' + Number(dst), 1);
},

/**
* Write cookie data
*
* @param {String} name
* @param {String} value
* @param {Number} days
*/
writeCookie: function(name, value, days) {
var expires = '';

if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = '; expires=' + date.toGMTString();
}
document.cookie = name + '=' + value + expires + '; path=/';
},

/**
* Read cookie data
*
* @param {String} name
* @returns {*}
*/
readCookie: function(name) {
var nameEq = name + '=';
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') {
c = c.substring(1,c.length);
}
if (c.indexOf(nameEq) == 0) {
return c.substring(nameEq.length,c.length);
}
}
return null;
}
};

})(Icinga, jQuery);

0 comments on commit 975985d

Please sign in to comment.