Хак: поддержка временных зон для каждого пользователя

Скажу сразу, что сделал хак быстро и не вникая в поддержку ЛайвСтритом хуков и модулей. Использую пока в девелоперской версии англоязычного проекта. Следовательно в бою не проверялось.
Поехали…

1) setup/config.php
Поскольку у меня планируется интернациональный проект, то по умолчанию я храню все даты в GMT. Для этого выставляю в конфиге

date_default_timezone_set('Europe/London');


Для любого проекта, где вы планируете использовать таймзоны правильным решением является хранение всех временных значений в GMT.

2) Добавляю пользователям поле в БД для хранения информации о таймзоне.

ALTER TABLE prefix_user ADD user_profile_timezone FLOAT NOT NULL DEFAULT '0';


2.1) Добавляю возможность чтения/записи этого нового значения объекта
Для этого добавляю в файл classes/modules/user/entity/User.entity.class.php две новые функции:

    public function getUserTimezone() {
        return $this->_aData['user_profile_timezone'];
    }    
    public function setUserTimezone($data) {
    	$this->_aData['user_profile_timezone']=$data;
    }

2.2) Добавляю возможность обновления таймзоны из формы редактирования профиля пользователя
Тут для не опытных товарищей будет несколько геморно:)
Надо в файл classes/actions/ActionSettings.class.php после 244 строчки добавить
$this->oUserCurrent->setUserTimezone(getRequest('profile_timezone'));


Далее в файле classes/modules/user/mapper/User.mapper.class.php находим функцию public function Update
и приводим ее к такому виду:
public function Update(UserEntity_User $oUser) {
		$sql = "UPDATE ".DB_TABLE_USER." 
			SET 
				user_password = ? ,
				user_mail = ? ,	
				user_key =? ,		
				user_skill = ? ,
				user_date_last = ? ,
				user_date_activate = ? ,
				user_date_comment_last = ? ,
				user_ip_last = ?, 
				user_rating = ? ,
				user_count_vote = ? ,
				user_activate = ? , 
				user_profile_name = ? , 
				user_profile_sex = ? , 
				user_profile_country = ? , 
				user_profile_region = ? , 
				user_profile_city = ? , 
				user_profile_birthday = ? , 
				user_profile_site = ? , 
				user_profile_site_name = ? , 
				user_profile_icq = ? , 
				user_profile_about = ? ,
				user_profile_date = ? ,
				user_profile_avatar = ?	,
				user_profile_avatar_type = ? ,	
				user_profile_foto = ? ,	
				user_settings_notice_new_topic = ?	,
				user_settings_notice_new_comment = ? ,
				user_settings_notice_new_talk = ?	,
				user_settings_notice_reply_comment = ? ,
				user_settings_notice_new_friend = ?,
				user_profile_timezone = ?
			WHERE user_id = ?
		";			
		if ($this->oDb->query($sql,$oUser->getPassword(),
								   $oUser->getMail(),
								   $oUser->getKey(),
								   $oUser->getSkill(),
								   $oUser->getDateLast(),
								   $oUser->getDateActivate(),
								   $oUser->getDateCommentLast(),
								   $oUser->getIpLast(),
								   $oUser->getRating(),
								   $oUser->getCountVote(),
								   $oUser->getActivate(),								   
								   $oUser->getProfileName(),
								   $oUser->getProfileSex(),
								   $oUser->getProfileCountry(),
								   $oUser->getProfileRegion(),
								   $oUser->getProfileCity(),
								   $oUser->getProfileBirthday(),
								   $oUser->getProfileSite(),
								   $oUser->getProfileSiteName(),
								   $oUser->getProfileIcq(),
								   $oUser->getProfileAbout(),	
								   $oUser->getProfileDate(),	
								   $oUser->getProfileAvatar(),	
								   $oUser->getProfileAvatarType(),
								   $oUser->getProfileFoto(),
								   $oUser->getSettingsNoticeNewTopic(),
								   $oUser->getSettingsNoticeNewComment(),
								   $oUser->getSettingsNoticeNewTalk(),
								   $oUser->getSettingsNoticeReplyComment(),	
								   $oUser->getSettingsNoticeNewFriend(),
								   $oUser->getUserTimezone(),
								   $oUser->getId())) {
			return true;
		}		
		return false;
	}


3) Добавляю возможность пользователю редактировать значение таймзоны для юзера
3.1) Создаю файл, который хранит список таймзон.
Сразу делал с возможность поддержки разных языков. Поэтому делаю так:
— создаю папку templates/language/modules/timezones/
— создаю в этой созданной папке файл english.php следующего содержания
<?php
return array(
    'timezones_name' => 'Your timezone',
	'timezones' => array(
	    '-12' => 'Enitwetok, Kwajalien',
	    '-11' => 'Midway Island, Samoa',
	    '-10' => 'Hawaii',
	    '-9' => 'Alaska',
	    '-8' => 'Pacific Time (US & Canada)',
	    '-7' => 'Mountain Time (US & Canada)',
	    '-6' => 'Central Time (US & Canada), Mexico City',
	    '-5' => 'Eastern Time (US & Canada), Bogota, Lima, Quito',
	    '-4' => 'Atlantic Time (Canada), Caracas, La Paz',
	    '-3.5' => 'Newfoundland',
	    '-3' => 'Brazil, Buenos Aires, Georgetown, Falkland Is.',
	    '-2' => 'Mid-Atlantic, Ascention Is., St Helena',
	    '-1' => 'Azores, Cape Verde Islands',
	    '0' => 'Casablanca, Dublin, Edinburgh, London, Lisbon, Monrovia',
	    '1' => 'Berlin, Brussels, Copenhagen, Madrid, Paris, Rome',
	    '2' => 'Kaliningrad, South Africa, Warsaw',
	    '3' => 'Baghdad, Riyadh, Moscow, Nairobi',
	    '3.5' => 'Tehran',
	    '4' => 'Abu Dhabi, Baku, Muscat, Tbilisi',
	    '4.5' => 'Kabul',
	    '5' => 'Ekaterinburg, Islamabad, Karachi, Tashkent',
	    '5.5' => 'Bombay, Calcutta, Madras, New Delhi',
	    '6' => 'Almaty, Colomba, Dhakra',
	    '7' => 'Bangkok, Hanoi, Jakarta',
	    '8' => 'Beijing, Hong Kong, Perth, Singapore, Taipei',
	    '9' => 'Osaka, Sapporo, Seoul, Tokyo, Yakutsk',
	    '9.5' => 'Adelaide, Darwin',
	    '10' => 'Melbourne, Papua New Guinea, Sydney, Vladivostok',
	    '11' => 'Magadan, New Caledonia, Solomon Islands',
	    '12' => 'Auckland, Wellington, Fiji, Marshall Island'
	)
);
?>


3.2) Добавляю вывод списка таймзон в форме редактирования профиля
Редактируем файл templates/skin/new/actions/ActionSettings/profile.tpl
Мне понравилось расположить выпадающий список таймзон над полем Страны. Поэтому я там и добавил:

                    <p>
		     <label for="profile_timezone">{$aLang.timezones_name}:</label><br />
                    <select class="w300" name="profile_timezone">
                        {foreach key=timezone_shift item=timezone_name from=$aLang.timezones}
                            <option value="{$timezone_shift}" {if $timezone_shift==$oUserCurrent->getUserTimezone()}selected{/if}>(GMT {if intval($timezone_shift) > 0}+{/if}{$timezone_shift|replace:'.5':':30'} hours) {$timezone_name}</option>
                        {/foreach}
                    </select><br />
		    </p>

Вы можете расположить код по вашему усмотрению :)

4) Добавляю обработку данных соответственно временной зоне пользователя.
Редактирую файл include/function.php
В функции func_date меняю строчку
$sDate=date($sFormat,$iDate);

на

    global $oRouter;
    $oUser=$oRouter->User_GetUserCurrent();
    if (!empty($oUser)){
        $userTimezone = $oUser->getUserTimezone();
        if (!empty($userTimezone)){
            $iDate += $userTimezone * 3600;
        }
    }
    $sDate=date($sFormat,$iDate);

Мне лично это место не нравится по причине его кривости. Но пока я не особо нашел, как сделать иначе. Буду рад за корректировки по этому пункту и в целом по реализации.
Не пинайте сильно :)

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.