Modernized the "timezone hack", made the config option a dropdown, and moved all timezone-related code into a new TimeZoneConfig class HEAD
authorDirk Haun <dirk@haun-online.de>
Sun Sep 20 11:00:03 2009 +0200 (5 months ago)
branchHEAD
changeset 7428df55886043f2
parent 733230e040149cbe
child 742901f95a3e4545
Modernized the "timezone hack", made the config option a dropdown, and moved all timezone-related code into a new TimeZoneConfig class
public_html/admin/configuration.php
public_html/admin/install/config-install.php
public_html/docs/history
public_html/lib-common.php
public_html/usersettings.php
sql/updates/mssql_1.6.0_to_1.6.1.php
sql/updates/mysql_1.6.0_to_1.6.1.php
system/classes/timezoneconfig.class.php
     1.1 --- a/public_html/admin/configuration.php	Sun Sep 20 10:41:17 2009 +0200
     1.2 +++ b/public_html/admin/configuration.php	Sun Sep 20 11:00:03 2009 +0200
     1.3 @@ -8,7 +8,7 @@
     1.4  // |                                                                           |
     1.5  // | Loads the administration UI and sends input to config.class               |
     1.6  // +---------------------------------------------------------------------------+
     1.7 -// | Copyright (C) 2007-2008 by the following authors:                         |
     1.8 +// | Copyright (C) 2007-2009 by the following authors:                         |
     1.9  // |                                                                           |
    1.10  // | Authors: Aaron Blankstein  - kantai AT gmail DOT com                      |
    1.11  // +---------------------------------------------------------------------------+
    1.12 @@ -84,6 +84,21 @@
    1.13      return $themes;
    1.14  }
    1.15  
    1.16 +/**
    1.17 +* Helper function: Provide timezone dropdown
    1.18 +*
    1.19 +* @return   array   Array of (timezone-long-name, timezone-short-name) pairs
    1.20 +*
    1.21 +*/
    1.22 +function configmanager_select_timezone_helper()
    1.23 +{
    1.24 +    global $_CONF;
    1.25 +
    1.26 +    require_once $_CONF['path_system'] . 'classes/timezoneconfig.class.php';
    1.27 +
    1.28 +    return array_flip(TimeZoneConfig::listAvailableTimeZones());
    1.29 +}
    1.30 +
    1.31  
    1.32  // MAIN
    1.33  $display = '';
     2.1 --- a/public_html/admin/install/config-install.php	Sun Sep 20 10:41:17 2009 +0200
     2.2 +++ b/public_html/admin/install/config-install.php	Sun Sep 20 11:00:03 2009 +0200
     2.3 @@ -291,7 +291,7 @@
     2.4      $c->add('thousand_separator',",",'text',6,29,NULL,440,TRUE);
     2.5      $c->add('decimal_separator',".",'text',6,29,NULL,450,TRUE);
     2.6      $c->add('decimal_count',"2",'text',6,29,NULL,460,TRUE);
     2.7 -    $c->add('timezone','Etc/GMT-6','text',6,29,NULL,490,FALSE);
     2.8 +    $c->add('timezone','UTC','select',6,29,NULL,490,FALSE);
     2.9  
    2.10      // Subgroup: Miscellaneous
    2.11      $c->add('sg_misc', NULL, 'subgroup', 7, 0, NULL, 0, TRUE);
     3.1 --- a/public_html/docs/history	Sun Sep 20 10:41:17 2009 +0200
     3.2 +++ b/public_html/docs/history	Sun Sep 20 11:00:03 2009 +0200
     3.3 @@ -3,6 +3,8 @@
     3.4  Oct ??, 2009 (1.6.1)
     3.5  ------------
     3.6  
     3.7 +- Modernized the "timezone hack", made the config option a dropdown, and moved
     3.8 +  all timezone-related code into a new TimeZoneConfig class [Dirk]
     3.9  - Changing the Post Mode in Advanced Editor mode selected the wrong tab
    3.10    (bug #0000980, patch provided by dengen)
    3.11  - Made the former $cc parameter for COM_mail an optional array of additional
     4.1 --- a/public_html/lib-common.php	Sun Sep 20 10:41:17 2009 +0200
     4.2 +++ b/public_html/lib-common.php	Sun Sep 20 11:00:03 2009 +0200
     4.3 @@ -130,12 +130,6 @@
     4.4      exit;
     4.5  }
     4.6  
     4.7 -// timezone hack - set the webserver's timezone
     4.8 -if( !empty( $_CONF['timezone'] ) && !ini_get( 'safe_mode' ) &&
     4.9 -        function_exists( 'putenv' )) {
    4.10 -    putenv( 'TZ=' . $_CONF['timezone'] );
    4.11 -}
    4.12 -
    4.13  
    4.14  // +---------------------------------------------------------------------------+
    4.15  // | Library Includes: You shouldn't have to touch anything below here         |
    4.16 @@ -160,6 +154,13 @@
    4.17  }
    4.18  
    4.19  /**
    4.20 +* Set the webserver's timezone
    4.21 +*/
    4.22 +
    4.23 +require_once $_CONF['path_system'] . 'classes/timezoneconfig.class.php';
    4.24 +TimeZoneConfig::setSystemTimeZone();
    4.25 +
    4.26 +/**
    4.27  * Include plugin class.
    4.28  * This is a poorly implemented class that was not very well thought out.
    4.29  * Still very necessary
     5.1 --- a/public_html/usersettings.php	Sun Sep 20 10:41:17 2009 +0200
     5.2 +++ b/public_html/usersettings.php	Sun Sep 20 11:00:03 2009 +0200
     5.3 @@ -518,36 +518,15 @@
     5.4          $preferences->set_var ('theme_selection', '');
     5.5      }
     5.6  
     5.7 -    require_once ('Date/TimeZone.php');
     5.8      // Timezone
     5.9 -    if (empty($_USER['tzid']) && isset($_CONF['timezone'])) {
    5.10 -        $timezone = $_CONF['timezone'];
    5.11 -    } else if (!empty($_USER['tzid'])) {
    5.12 -        $timezone = $_USER['tzid'];
    5.13 -    } else {
    5.14 -        $tz_obj = Date_TimeZone::getDefault();
    5.15 -        $timezone = $tz_obj->id;
    5.16 -    }
    5.17 -    $selection = '<select id="tzid" name="tzid">' . LB;
    5.18 +    require_once $_CONF['path_system'] . 'classes/timezoneconfig.class.php';
    5.19  
    5.20 -    $T = $GLOBALS['_DATE_TIMEZONE_DATA'];
    5.21 +    $timezone = TimeZoneConfig::getUserTimeZone();
    5.22 +    $selection = TimeZoneConfig::getTimeZoneDropDown($timezone,
    5.23 +            array('id' => 'tzid', 'name' => 'tzid'));
    5.24  
    5.25 -    foreach ($T as $tzid => $tDetails) {
    5.26 -        $tzcode = str_replace('_', ' ', $tzid);
    5.27 -        $tzcode = htmlspecialchars($tzcode);
    5.28 -        $selection .= '<option value="' . $tzcode . '"';
    5.29 -        if ($timezone == $tzcode) {
    5.30 -            $selection .= ' selected="selected"';
    5.31 -        }
    5.32 -        $hours = $tDetails['offset'] / (3600 * 1000);
    5.33 -        if ($hours > 0) {
    5.34 -            $hours = "+$hours";
    5.35 -        }
    5.36 -        $selection .= ">$hours, {$tDetails['shortname']} ($tzcode)</option>" . LB;
    5.37 -    }
    5.38 -    $selection .= '</select>';
    5.39 -    $preferences->set_var ('timezone_selector', $selection);
    5.40 -    $preferences->set_var ('lang_timezone', $LANG04[158]);
    5.41 +    $preferences->set_var('timezone_selector', $selection);
    5.42 +    $preferences->set_var('lang_timezone', $LANG04[158]);
    5.43  
    5.44      if ($A['noicons'] == '1') {
    5.45          $preferences->set_var ('noicons_checked', 'checked="checked"');
     6.1 --- a/sql/updates/mssql_1.6.0_to_1.6.1.php	Sun Sep 20 10:41:17 2009 +0200
     6.2 +++ b/sql/updates/mssql_1.6.0_to_1.6.1.php	Sun Sep 20 11:00:03 2009 +0200
     6.3 @@ -23,6 +23,10 @@
     6.4      $c->add('meta_description','Geeklog, the open source content management system designed with security in mind.','text',0,0,NULL,2010,TRUE);
     6.5      $c->add('meta_keywords','Geeklog, Blog, Content Management System, CMS, Open Source, Security','text',0,0,NULL,2020,TRUE);
     6.6  
     6.7 +    // the timezone config option is a dropdown now
     6.8 +    $utc = addslashes(serialize('UTC')); // change default timezone to UTC
     6.9 +    DB_query("UPDATE {$_TABLES['conf_values']} SET type = 'select', selectionArray = -1, default_value = '$utc' WHERE name = 'timezone' AND group_name = 'Core'");
    6.10 +
    6.11      return true;
    6.12  }
    6.13  
     7.1 --- a/sql/updates/mysql_1.6.0_to_1.6.1.php	Sun Sep 20 10:41:17 2009 +0200
     7.2 +++ b/sql/updates/mysql_1.6.0_to_1.6.1.php	Sun Sep 20 11:00:03 2009 +0200
     7.3 @@ -24,6 +24,10 @@
     7.4      $c->add('meta_description','Geeklog, the open source content management system designed with security in mind.','text',0,0,NULL,2010,TRUE);
     7.5      $c->add('meta_keywords','Geeklog, Blog, Content Management System, CMS, Open Source, Security','text',0,0,NULL,2020,TRUE);
     7.6  
     7.7 +    // the timezone config option is a dropdown now
     7.8 +    $utc = addslashes(serialize('UTC')); // change default timezone to UTC
     7.9 +    DB_query("UPDATE {$_TABLES['conf_values']} SET type = 'select', selectionArray = -1, default_value = '$utc' WHERE name = 'timezone' AND group_name = 'Core'");
    7.10 +
    7.11      return true;
    7.12  }
    7.13  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/system/classes/timezoneconfig.class.php	Sun Sep 20 11:00:03 2009 +0200
     8.3 @@ -0,0 +1,260 @@
     8.4 +<?php
     8.5 +
     8.6 +/* Reminder: always indent with 4 spaces (no tabs). */
     8.7 +// +---------------------------------------------------------------------------+
     8.8 +// | Geeklog 1.6                                                               |
     8.9 +// +---------------------------------------------------------------------------+
    8.10 +// | timezoneconfig.class.php                                                  |
    8.11 +// |                                                                           |
    8.12 +// | Helper class for time zone handling                                       |
    8.13 +// +---------------------------------------------------------------------------+
    8.14 +// | Copyright (C) 2009 by the following authors:                              |
    8.15 +// |                                                                           |
    8.16 +// | Authors: Dirk Haun             - dirk AT haun-online DOT de               |
    8.17 +// | based on earlier work by Oliver Spiesshofer, Yew Loong, and others        |
    8.18 +// +---------------------------------------------------------------------------+
    8.19 +// |                                                                           |
    8.20 +// | This program is free software; you can redistribute it and/or             |
    8.21 +// | modify it under the terms of the GNU General Public License               |
    8.22 +// | as published by the Free Software Foundation; either version 2            |
    8.23 +// | of the License, or (at your option) any later version.                    |
    8.24 +// |                                                                           |
    8.25 +// | This program is distributed in the hope that it will be useful,           |
    8.26 +// | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
    8.27 +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
    8.28 +// | GNU General Public License for more details.                              |
    8.29 +// |                                                                           |
    8.30 +// | You should have received a copy of the GNU General Public License         |
    8.31 +// | along with this program; if not, write to the Free Software Foundation,   |
    8.32 +// | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
    8.33 +// |                                                                           |
    8.34 +// +---------------------------------------------------------------------------+
    8.35 +
    8.36 +/**
    8.37 +* Geeklog Time Zone Config class
    8.38 +*
    8.39 +* A collection of static (for now) methods dealing with time zone handling.
    8.40 +*
    8.41 +* For the original "Timezone Hack" discussion, see
    8.42 +* @link http://www.geeklog.net/forum/viewtopic.php?showtopic=21232
    8.43 +* 
    8.44 +* @author Dirk Haun, dirk AT haun-online DOT de
    8.45 +* 
    8.46 +*/
    8.47 +class TimeZoneConfig {
    8.48 +
    8.49 +    /**
    8.50 +    * Set the system's timezone
    8.51 +    *
    8.52 +    * @param    string  $tz     timezone to set; use $_CONF['timezone'] if empty
    8.53 +    * @return   void
    8.54 +    * @static
    8.55 +    *
    8.56 +    */
    8.57 +    function setSystemTimeZone($tz = '')
    8.58 +    {
    8.59 +        global $_CONF;
    8.60 +
    8.61 +        if (empty($tz) && !empty($_CONF['timezone'])) {
    8.62 +            $tz = $_CONF['timezone'];
    8.63 +        }
    8.64 +
    8.65 +        if (! empty($tz)) {
    8.66 +            if (function_exists('date_default_timezone_set')) {
    8.67 +                if (! @date_default_timezone_set($tz)) {
    8.68 +                    date_default_timezone_set('UTC');
    8.69 +                    COM_errorLog("Timezone '$tz' not valid - using 'UTC' instead", 1);
    8.70 +                }
    8.71 +            } elseif (!ini_get('safe_mode') && function_exists('putenv')) {
    8.72 +                // aka "Timezone Hack"
    8.73 +                putenv('TZ=' . $tz);
    8.74 +            }
    8.75 +        } elseif (function_exists('date_default_timezone_get')) {
    8.76 +            // this is not ideal but will stop PHP 5.3.0ff from complaining ...
    8.77 +            date_default_timezone_set(@date_default_timezone_get());
    8.78 +        }
    8.79 +    }
    8.80 +
    8.81 +    /**
    8.82 +    * Get the user's preferred timezone
    8.83 +    *
    8.84 +    * @return   string  name of the timezone
    8.85 +    * @static
    8.86 +    *
    8.87 +    */
    8.88 +    function getUserTimeZone()
    8.89 +    {
    8.90 +        global $_CONF, $_USER;
    8.91 +
    8.92 +        if (! empty($_USER['tzid'])) {
    8.93 +            $timezone = $_USER['tzid'];
    8.94 +        } elseif (! empty($_CONF['timezone'])) {
    8.95 +            $timezone = $_CONF['timezone'];
    8.96 +        } else {
    8.97 +            require_once 'Date/TimeZone.php';
    8.98 +
    8.99 +            $tz_obj = Date_TimeZone::getDefault();
   8.100 +            $timezone = $tz_obj->id;
   8.101 +        }
   8.102 +
   8.103 +        return $timezone;
   8.104 +    }
   8.105 +
   8.106 +    /**
   8.107 +    * Provide a dropdown menu of the available timezones
   8.108 +    *
   8.109 +    * @return   string  HTML for the dropdown
   8.110 +    * @static
   8.111 +    *
   8.112 +    */
   8.113 +    function getTimeZoneDropDown($selected = '', $attributes = array())
   8.114 +    {
   8.115 +        $timezones = TimeZoneConfig::listAvailableTimeZones();
   8.116 +
   8.117 +        $selection = '<select';
   8.118 +        foreach ($attributes as $name => $value) {
   8.119 +            $selection .= sprintf(' %s="%s"', $name, $value);
   8.120 +        }
   8.121 +        $selection .= '>' . LB;
   8.122 +
   8.123 +        foreach ($timezones as $tzid => $tzdisplay) {
   8.124 +            $selection .= '<option value="' . $tzid . '"';
   8.125 +            if (!empty($selected) && ($selected == $tzid)) {
   8.126 +                $selection .= ' selected="selected"';
   8.127 +            }
   8.128 +            $selection .= ">$tzdisplay</option>" . LB;
   8.129 +        }
   8.130 +        $selection .= '</select>';
   8.131 +
   8.132 +        return $selection;
   8.133 +    }
   8.134 +
   8.135 +    /**
   8.136 +    * Provide a list of available timezones
   8.137 +    *
   8.138 +    * @return   array   array of (timezone-short-name, timezone-long-name) pairs
   8.139 +    * @static
   8.140 +    *
   8.141 +    */
   8.142 +    function listAvailableTimeZones()
   8.143 +    {
   8.144 +        $timezones = array();
   8.145 +
   8.146 +        // use only timezones that contain one of these
   8.147 +        $useonly = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia',
   8.148 +                         'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific',
   8.149 +                         'UTC');
   8.150 +
   8.151 +        // check if we can use the DateTimeZone class
   8.152 +        $useDateTimeZone = false;
   8.153 +        if (class_exists('DateTimeZone') && class_exists('ReflectionClass')) {
   8.154 +            $rc = new ReflectionClass('DateTimeZone');
   8.155 +            if ($rc->hasMethod('listAbbreviations')) {
   8.156 +                $useDateTimeZone = true;
   8.157 +            }
   8.158 +        }
   8.159 +
   8.160 +        if ($useDateTimeZone) {
   8.161 +
   8.162 +            $T = DateTimeZone::listAbbreviations();
   8.163 +            foreach ($T as $tzid => $entries) {
   8.164 +                $shortname = strtoupper($tzid);
   8.165 +                foreach ($entries as $data) {
   8.166 +                    $tzcheck = explode('/', $data['timezone_id']);
   8.167 +                    if (! in_array($tzcheck[0], $useonly)) {
   8.168 +                        continue;
   8.169 +                    }
   8.170 +
   8.171 +                    $hours = $data['offset'] / 3600;
   8.172 +                    $hours = ((int) ($hours * 100) / 100);
   8.173 +                    if ($hours > 0) {
   8.174 +                        $hours = "+$hours";
   8.175 +                    }
   8.176 +
   8.177 +                    $tzcode = str_replace('_', ' ', $data['timezone_id']);
   8.178 +                    $tzcode = htmlspecialchars($tzcode);
   8.179 +                    $formattedTimezone = "$hours, $shortname ($tzcode)";
   8.180 +                    $timezones[$data['timezone_id']] = $formattedTimezone;
   8.181 +                }
   8.182 +            }
   8.183 +
   8.184 +        } else { // DateTimeZone not available - use PEAR Date class
   8.185 +
   8.186 +            require_once 'Date/TimeZone.php';
   8.187 +
   8.188 +            $T = $GLOBALS['_DATE_TIMEZONE_DATA'];
   8.189 +
   8.190 +            foreach ($T as $tzid => $tDetails) {
   8.191 +                $tzcheck = explode('/', $tzid);
   8.192 +                if (! in_array($tzcheck[0], $useonly)) {
   8.193 +                    continue;
   8.194 +                }
   8.195 +                if (!empty($tzcheck[1]) &&
   8.196 +                        (strpos($tzcheck[1], 'Riyadh') === 0)) {
   8.197 +                    // these time zones are based on solar time and not widely
   8.198 +                    // supported - skip
   8.199 +                    continue;
   8.200 +                }
   8.201 +
   8.202 +                $tzcode = str_replace('_', ' ', $tzid);
   8.203 +                $tzcode = htmlspecialchars($tzcode);
   8.204 +                $hours = $tDetails['offset'] / (3600 * 1000);
   8.205 +                $hours = ((int) ($hours * 100) / 100);
   8.206 +                if ($hours > 0) {
   8.207 +                    $hours = "+$hours";
   8.208 +                }
   8.209 +
   8.210 +                $formattedTimezone = "$hours, {$tDetails['shortname']} ($tzcode)";
   8.211 +                $timezones[$tzid] = $formattedTimezone;
   8.212 +            }
   8.213 +
   8.214 +        }
   8.215 +
   8.216 +        uasort($timezones, 'TimeZoneConfig::_sort_by_timezone');
   8.217 +
   8.218 +        return $timezones;
   8.219 +    }
   8.220 +
   8.221 +    /**
   8.222 +    * Helper method: Sort timezone entries
   8.223 +    *
   8.224 +    * @param    string  $tz1    first timezone
   8.225 +    * @param    string  $tz2    second timezone
   8.226 +    * @return   int             0: equal, <0: first<second, >0: first>second
   8.227 +    * @static
   8.228 +    * @access   private
   8.229 +    *
   8.230 +    */
   8.231 +    function _sort_by_timezone($tz1, $tz2)
   8.232 +    {
   8.233 +        $p1 = explode(',', $tz1);
   8.234 +        $p2 = explode(',', $tz2);
   8.235 +
   8.236 +        // compare offsets
   8.237 +        $o1 = $p1[0];
   8.238 +        $o2 = $p2[0];
   8.239 +        if ($o1 != $o2) {
   8.240 +            return ($o1 < $o2 ? -1 : 1);
   8.241 +        }
   8.242 +
   8.243 +        // drop offset, pop timezone name, then add it to the end again
   8.244 +        array_shift($p1);
   8.245 +        $tz1 = trim(implode(',', $p1));
   8.246 +        $p1 = explode(' ', $tz1);
   8.247 +        $x1 = array_shift($p1);
   8.248 +        $p1[] = $x1;
   8.249 +        $tz1 = implode(' ', $p1);
   8.250 +
   8.251 +        array_shift($p2);
   8.252 +        $tz2 = trim(implode(',', $p2));
   8.253 +        $p2 = explode(' ', $tz2);
   8.254 +        $x2 = array_shift($p2);
   8.255 +        $p2[] = $x2;
   8.256 +        $tz2 = implode(' ', $p2);
   8.257 +
   8.258 +        return strcmp($tz1, $tz2);
   8.259 +    }
   8.260 +
   8.261 +}
   8.262 +
   8.263 +?>