* Time zone have to be specified in settings

This commit is contained in:
Max Pozdeev 2010-10-25 10:45:04 +04:00
parent 3c3cfad44b
commit c405f03ce7
9 changed files with 100 additions and 76 deletions

View file

@ -11,7 +11,7 @@ set_exception_handler('myExceptionHandler');
require_once('./init.php');
$lang = Lang::instance();
$db = DBConnection::instance();
if(isset($_GET['loadLists']))
{
@ -76,8 +76,6 @@ elseif(isset($_GET['loadTasks']))
if($sort == 1) $sqlSort .= "prio DESC, ddn ASC, duedate ASC, ow ASC";
elseif($sort == 2) $sqlSort .= "ddn ASC, duedate ASC, prio DESC, ow ASC";
else $sqlSort .= "ow ASC";
$tz = (int)_get('tz');
if(Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0) $tz = round(date('Z')/60);
$t = array();
$t['total'] = 0;
$t['list'] = array();
@ -85,7 +83,7 @@ elseif(isset($_GET['loadTasks']))
while($r = $q->fetch_assoc($q))
{
$t['total']++;
$t['list'][] = prepareTaskRow($r, $tz);
$t['list'][] = prepareTaskRow($r);
}
if(_get('setCompl') && have_write_access()) {
$bitwise = (_get('compl') == 0) ? 'taskview & ~1' : 'taskview | 1';
@ -120,8 +118,6 @@ elseif(isset($_GET['newTask']))
exit;
}
if(Config::get('autotag')) $tags .= ','._post('tag');
$tz = (int)_post('tz');
if(Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60);
$ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0");
$db->ex("BEGIN");
$db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio) VALUES (?,?,?,?,?,?,?)",
@ -137,7 +133,7 @@ elseif(isset($_GET['newTask']))
}
$db->ex("COMMIT");
$r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id");
$t['list'][] = prepareTaskRow($r, $tz);
$t['list'][] = prepareTaskRow($r);
$t['total'] = 1;
echo json_encode($t);
exit;
@ -161,8 +157,6 @@ elseif(isset($_GET['fullNewTask']))
}
$tags = trim(_post('tags'));
if(Config::get('autotag')) $tags .= ','._post('tag');
$tz = (int)_post('tz');
if( Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60);
$ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0");
$db->ex("BEGIN");
$db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio,note,duedate) VALUES(?,?,?,?,?,?,?,?,?)",
@ -178,7 +172,7 @@ elseif(isset($_GET['fullNewTask']))
}
$db->ex("COMMIT");
$r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id");
$t['list'][] = prepareTaskRow($r, $tz);
$t['list'][] = prepareTaskRow($r);
$t['total'] = 1;
echo json_encode($t);
exit;
@ -204,11 +198,9 @@ elseif(isset($_GET['completeTask']))
$dateCompleted = $compl ? time() : 0;
$db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=?,d_edited=? WHERE id=$id",
array($dateCompleted, time()) );
$tz = (int)_post('tz');
if(Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0) $tz = round(date('Z')/60);
$t = array();
$t['total'] = 1;
$t['list'][] = array('id'=>$id, 'compl'=>$compl, 'ow'=>$ow, 'dateCompleted'=>$dateCompleted?htmlarray(timestampToDatetime($dateCompleted, $tz)):'');
$t['list'][] = array('id'=>$id, 'compl'=>$compl, 'ow'=>$ow, 'dateCompleted'=>$dateCompleted?htmlarray(timestampToDatetime($dateCompleted)):'');
echo json_encode($t);
exit;
}
@ -243,8 +235,6 @@ elseif(isset($_GET['editTask']))
echo json_encode($t);
exit;
}
$tz = (int)_post('tz');
if( Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60);
$tags = trim(_post('tags'));
$db->ex("BEGIN");
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id");
@ -259,7 +249,7 @@ elseif(isset($_GET['editTask']))
$db->ex("COMMIT");
$r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id");
if($r) {
$t['list'][] = prepareTaskRow($r, $tz);
$t['list'][] = prepareTaskRow($r);
$t['total'] = 1;
}
echo json_encode($t);
@ -530,25 +520,25 @@ elseif(isset($_GET['setShowNotesInList']))
###################################################################################################
function prepareTaskRow($r, $tz)
function prepareTaskRow($r)
{
global $lang;
$dueA = prepare_duedate($r['duedate'], $tz);
$lang = Lang::instance();
$dueA = prepare_duedate($r['duedate']);
$formatCreatedInline = $formatCompletedInline = 'M d';
if(date('Y') != date('Y',$r['d_created'])) $formatCreatedInline = 'M Y';
if($r['d_completed'] && date('Y') != date('Y',$r['d_completed'])) $formatCompletedInline = 'M Y';
$dCreated = timestampToDatetime($r['d_created'], $tz);
$dCompleted = $r['d_completed'] ? timestampToDatetime($r['d_completed'], $tz) : '';
$dCreated = timestampToDatetime($r['d_created']);
$dCompleted = $r['d_completed'] ? timestampToDatetime($r['d_completed']) : '';
return array(
'id' => $r['id'],
'title' => escapeTags($r['title']),
'date' => htmlarray($dCreated),
'dateInline' => htmlarray(formatTime($formatCreatedInline, $r['d_created'], $tz)),
'dateInline' => htmlarray(formatTime($formatCreatedInline, $r['d_created'])),
'dateInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_created'), $dCreated)),
'dateCompleted' => htmlarray($dCompleted),
'dateCompletedInline' => $r['d_completed'] ? htmlarray(formatTime($formatCompletedInline, $r['d_completed'], $tz)) : '',
'dateCompletedInline' => $r['d_completed'] ? htmlarray(formatTime($formatCompletedInline, $r['d_completed'])) : '',
'dateCompletedInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_completed'), $dCompleted)),
'compl' => (int)$r['compl'],
'prio' => $r['prio'],
@ -559,7 +549,7 @@ function prepareTaskRow($r, $tz)
'tags_ids' => htmlarray($r['tags_ids']),
'duedate' => $dueA['formatted'],
'dueClass' => $dueA['class'],
'dueStr' => htmlarray($r['compl'] && $dueA['timestamp'] ? formatTime($formatCompletedInline, $dueA['timestamp'], $tz) : $dueA['str']),
'dueStr' => htmlarray($r['compl'] && $dueA['timestamp'] ? formatTime($formatCompletedInline, $dueA['timestamp']) : $dueA['str']),
'dueInt' => date2int($r['duedate']),
'dueTitle' => htmlarray(sprintf($lang->get('taskdate_inline_duedate'), $dueA['formatted'])),
);
@ -567,7 +557,7 @@ function prepareTaskRow($r, $tz)
function check_read_access($listId = null)
{
global $db;
$db = DBConnection::instance();
if(Config::get('password') == '') return true;
if(is_logged()) return true;
if($listId)
@ -631,7 +621,7 @@ function prepareTags($tagsStr)
function getOrCreateTag($name)
{
global $db;
$db = DBConnection::instance();
$tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name));
if($tagId) return array('id'=>$tagId, 'name'=>$name);
@ -641,14 +631,14 @@ function getOrCreateTag($name)
function getTagId($tag)
{
global $db;
$db = DBConnection::instance();
$id = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($tag));
return $id ? $id : 0;
}
function get_task_tags($id)
{
global $db;
$db = DBConnection::instance();
$q = $db->dq("SELECT tag_id FROM {$db->prefix}tag2task WHERE task_id=?", $id);
$a = array();
while($r = $q->fetch_row()) {
@ -660,7 +650,7 @@ function get_task_tags($id)
function addTaskTags($taskId, $tagIds, $listId)
{
global $db;
$db = DBConnection::instance();
if(!$tagIds) return;
foreach($tagIds as $tagId)
{
@ -734,17 +724,17 @@ function parse_duedate($s)
return "$y-$m-$d";
}
function prepare_duedate($duedate, $tz)
function prepare_duedate($duedate)
{
global $lang;
$lang = Lang::instance();
$a = array( 'class'=>'', 'str'=>'', 'formatted'=>'', 'timestamp'=>0 );
if($duedate == '') {
return $a;
}
$ad = explode('-', $duedate);
$at = explode('-', gmdate('Y-m-d', time() + $tz*60));
$a['timestamp'] = gmmktime(0,0,0,$ad[1],$ad[2],$ad[0]) + $tz*60;
$at = explode('-', date('Y-m-d'));
$a['timestamp'] = mktime(0,0,0,$ad[1],$ad[2],$ad[0]);
$diff = mktime(0,0,0,$ad[1],$ad[2],$ad[0]) - mktime(0,0,0,$at[1],$at[2],$at[0]);
if($diff < -604800 && $ad[0] == $at[0]) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); }
@ -811,7 +801,7 @@ function myExceptionHandler($e)
function deleteTask($id)
{
check_write_access();
global $db;
$db = DBConnection::instance();
$db->ex("BEGIN");
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id");
//TODO: delete unused tags?
@ -824,7 +814,7 @@ function deleteTask($id)
function moveTask($id, $listId)
{
check_write_access();
global $db;
$db = DBConnection::instance();
// Check task exists and not in target list
$r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=?", array($id));

View file

@ -73,7 +73,7 @@ class Config
'lang' => array('default'=>'en', 'type'=>'s'),
'password' => array('default'=>'', 'type'=>'s'),
'smartsyntax' => array('default'=>1, 'type'=>'i'),
'autotz' => array('default'=>1, 'type'=>'i'),
'timezone' => array('default'=>'UTC', 'type'=>'s'),
'autotag' => array('default'=>1, 'type'=>'i'),
'duedateformat' => array('default'=>1, 'type'=>'i'),
'firstdayofweek' => array('default'=>1, 'type'=>'i'),
@ -176,5 +176,25 @@ function generateUUID()
);
}
class DBConnection
{
protected static $instance;
public static function init($instance)
{
self::$instance = $instance;
return $instance;
}
public static function instance()
{
if (!isset(self::$instance)) {
//$c = __CLASS__;
$c = 'DBConnection';
self::$instance = new $c;
}
return self::$instance;
}
}
?>

View file

@ -31,8 +31,8 @@ $config['password'] = "";
# To disable smart syntax uncomment the line below
#$config['smartsyntax'] = 0;
# To disable auto detecting user time zone uncomment the line below
#$config['autotz'] = 0;
# Default Time zone
$config['timezone'] = 'UTC';
# To disable auto adding selected tag comment out the line below or set value to 0
$config['autotag'] = 1;

View file

@ -16,11 +16,13 @@ if(!isset($config)) global $config;
Config::loadConfig($config);
unset($config);
date_default_timezone_set(Config::get('timezone'));
# MySQL Database Connection
if(Config::get('db') == 'mysql')
{
require_once(MTTPATH. 'class.db.mysql.php');
$db = new Database_Mysql;
$db = DBConnection::init(new Database_Mysql);
$db->connect(Config::get('mysql.host'), Config::get('mysql.user'), Config::get('mysql.password'), Config::get('mysql.db'));
$db->dq("SET NAMES utf8");
}
@ -29,7 +31,7 @@ if(Config::get('db') == 'mysql')
elseif(Config::get('db') == 'sqlite')
{
require_once(MTTPATH. 'class.db.sqlite3.php');
$db = new Database_Sqlite3;
$db = DBConnection::init(new Database_Sqlite3);
$db->connect(MTTPATH. 'db/todolist.db');
}
else {
@ -67,19 +69,18 @@ function is_logged()
return true;
}
function timestampToDatetime($timestamp, $tz)
function timestampToDatetime($timestamp)
{
$format = Config::get('dateformat') .' '. (Config::get('clock') == 12 ? 'g:i A' : 'H:i');
return formatTime($format, $timestamp, $tz);
return formatTime($format, $timestamp);
}
function formatTime($format, $timestamp=0, $tz=null)
function formatTime($format, $timestamp=0)
{
$lang = Lang::instance();
if($timestamp == 0) $timestamp = time();
if(is_null($tz)) $tz = round(date('Z')/60);
$newformat = strtr($format, array('F'=>'%1', 'M'=>'%2'));
$adate = explode(',', gmdate('n,'.$newformat, $timestamp + $tz*60), 2);
$adate = explode(',', date('n,'.$newformat, $timestamp), 2);
$s = $adate[1];
if($newformat != $format)
{

View file

@ -111,8 +111,7 @@ class DefaultLang
'set_newpass_descr' => "(leave blank if won't change current password)",
'set_smartsyntax' => "Smart syntax",
'set_smartsyntax_descr' => "(/priority/ task /tags/)",
'set_autotz' => "Automatic timezone",
'set_autotz_descr' => "(determines timezone offset of user environment with javascript)",
'set_timezone' => "Time zone",
'set_autotag' => "Autotagging",
'set_autotag_descr' => "(automatically adds tag of current tag filter to newly created task)",
'set_sessions' => "Session handling mechanism",

View file

@ -113,8 +113,7 @@ class Lang extends DefaultLang
'set_newpass_descr' => "(leave blank if won't change current password)",
'set_smartsyntax' => "Smart syntax",
'set_smartsyntax_descr' => "(/priority/ task /tags/)",
'set_autotz' => "Automatic timezone",
'set_autotz_descr' => "(determines timezone offset of user environment with javascript)",
'set_timezone' => "Time zone",
'set_autotag' => "Autotagging",
'set_autotag_descr' => "(automatically adds tag of current tag filter to newly created task)",
'set_sessions' => "Session handling mechanism",

View file

@ -704,7 +704,6 @@ function loadTasks(opts)
sort: curList.sort,
search: filter.search,
tag: _mtt.filter.getTags(true),
tz: tz(),
setCompl: opts.setCompl
}, function(json){
taskList.length = 0;
@ -799,7 +798,7 @@ function prepareDuedate(item)
function submitNewTask(form)
{
if(form.task.value == '') return false;
_mtt.db.request('newTask', { list:curList.id, title: form.task.value, tz:tz(), tag:_mtt.filter.getTags() }, function(json){
_mtt.db.request('newTask', { list:curList.id, title: form.task.value, tag:_mtt.filter.getTags() }, function(json){
if(!json.total) return;
$('#total').text( parseInt($('#total').text()) + 1 );
taskCnt.total++;
@ -917,11 +916,6 @@ function setSort(v, init)
};
function tz()
{
return -1 * (new Date()).getTimezoneOffset();
};
function changeTaskCnt(task, dir, old)
{
if(dir > 0) dir = 1;
@ -1064,7 +1058,7 @@ function completeTask(id, ch)
if(!taskList[id]) return; //click on already removed from the list while anim. effect
var compl = 0;
if(ch.checked) compl = 1;
_mtt.db.request('completeTask', {id:id, compl:compl, list:curList.id, tz:tz()}, function(json){
_mtt.db.request('completeTask', {id:id, compl:compl, list:curList.id}, function(json){
if(!parseInt(json.total)) return;
var item = json.list[0];
if(item.compl) $('#taskrow_'+id).addClass('task-completed');
@ -1170,7 +1164,7 @@ function showEditForm(isAdd)
if(_mtt.options.autotag) form.tags.value = _mtt.filter.getTags();
if($('#task').val() != '')
{
_mtt.db.request('parseTaskStr', { list:curList.id, title:$('#task').val(), tz:tz(), tag:_mtt.filter.getTags() }, function(json){
_mtt.db.request('parseTaskStr', { list:curList.id, title:$('#task').val(), tag:_mtt.filter.getTags() }, function(json){
if(!json) return;
form.task.value = json.title
form.tags.value = (form.tags.value != '') ? form.tags.value +', '+ json.tags : json.tags;
@ -1194,7 +1188,7 @@ function saveTask(form)
if(form.isadd.value != 0)
return submitFullTask(form);
_mtt.db.request('editTask', {id:form.id.value, list:curList.id, tz:tz(), title: form.task.value, note:form.note.value,
_mtt.db.request('editTask', {id:form.id.value, list:curList.id, title: form.task.value, note:form.note.value,
prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value},
function(json){
if(!parseInt(json.total)) return;

View file

@ -50,21 +50,21 @@ mytinytodoStorageAjax.prototype =
})
*/
$.getJSON(this.mtt.mttUrl+'ajax.php?loadTasks&list='+params.list+'&compl='+params.compl+'&sort='+params.sort+'&tz='+params.tz+q, callback);
$.getJSON(this.mtt.mttUrl+'ajax.php?loadTasks&list='+params.list+'&compl='+params.compl+'&sort='+params.sort+q, callback);
},
newTask: function(params, callback)
{
$.post(this.mtt.mttUrl+'ajax.php?newTask',
{ list:params.list, title: params.title, tz:params.tz, tag:params.tag }, callback, 'json');
{ list:params.list, title: params.title, tag:params.tag }, callback, 'json');
},
fullNewTask: function(params, callback)
{
$.post(this.mtt.mttUrl+'ajax.php?fullNewTask',
{ list:params.list, tz:params.tz, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate },
{ list:params.list, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate },
callback, 'json');
},
@ -72,7 +72,7 @@ mytinytodoStorageAjax.prototype =
editTask: function(params, callback)
{
$.post(this.mtt.mttUrl+'ajax.php?editTask='+params.id,
{ id:params.id, list:params.list, tz:params.tz, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate },
{ id:params.id, list:params.list, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate },
callback, 'json');
},
@ -85,7 +85,7 @@ mytinytodoStorageAjax.prototype =
completeTask: function(params, callback)
{
$.post(this.mtt.mttUrl+'ajax.php?completeTask='+params.id, { id:params.id, compl:params.compl, tz:params.tz }, callback, 'json');
$.post(this.mtt.mttUrl+'ajax.php?completeTask='+params.id, { id:params.id, compl:params.compl }, callback, 'json');
},
@ -127,7 +127,7 @@ mytinytodoStorageAjax.prototype =
parseTaskStr: function(params, callback)
{
$.post(this.mtt.mttUrl+'ajax.php?parseTaskStr', { list:params.list, title:params.title, tz:params.tz, tag:params.tag }, callback, 'json');
$.post(this.mtt.mttUrl+'ajax.php?parseTaskStr', { list:params.list, title:params.title, tag:params.tag }, callback, 'json');
},

View file

@ -25,7 +25,14 @@ if(isset($_POST['save']))
if(isset($_POST['password']) && $_POST['password'] != '') Config::set('password', $_POST['password']);
elseif(!_post('allowpassword')) Config::set('password', '');
Config::set('smartsyntax', (int)_post('smartsyntax'));
Config::set('autotz', (int)_post('autotz'));
// Do not set invalid timezone
try {
$tz = trim(_post('timezone'));
$testTZ = new DateTimeZone($tz); //will throw Exception on invalid timezone
Config::set('timezone', $tz);
}
catch (Exception $e) {
}
Config::set('autotag', (int)_post('autotag'));
Config::set('session', _post('session'));
Config::set('firstdayofweek', (int)_post('firstdayofweek'));
@ -94,19 +101,34 @@ function selectOptions($a, $value, $default=null)
return $s;
}
function selectOptionsA($a, $value, $default=null)
/*
@param array $a array of id=>array(name, optional title)
@param mixed $key Key of OPTION to be selected
@param mixed $default Default key if $key is not present in $a
*/
function selectOptionsA($a, $key, $default=null)
{
if(!$a) return '';
$s = '';
if($default !== null && !isset($a[$value])) $value = $default;
if($default !== null && !isset($a[$key])) $key = $default;
foreach($a as $k=>$v) {
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$value?'selected="selected"':'').
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$key?'selected="selected"':'').
(isset($v['title']) ? ' title="'.htmlspecialchars($v['title']).'"' : '').
'>'.htmlspecialchars($v['name']).'</option>';
}
return $s;
}
function timezoneIdentifiers()
{
$zones = DateTimeZone::listIdentifiers();
$a = array();
foreach($zones as $v) {
$a[$v] = $v;
}
return $a;
}
?>
<div><a href="#" class="mtt-back-button"><?php _e('go_back');?></a></div>
@ -148,13 +170,6 @@ function selectOptionsA($a, $value, $default=null)
<label><input type="radio" name="smartsyntax" value="0" <?php if(!_c('smartsyntax')) echo 'checked="checked"'; ?> /><?php _e('set_disabled');?></label>
</td></tr>
<tr>
<th><?php _e('set_autotz');?>:<br/><span class="descr"><?php _e('set_autotz_descr');?></span></th>
<td>
<label><input type="radio" name="autotz" value="1" <?php if(_c('autotz')) echo 'checked="checked"'; ?> /><?php _e('set_enabled');?></label> <br/>
<label><input type="radio" name="autotz" value="0" <?php if(!_c('autotz')) echo 'checked="checked"'; ?> /><?php _e('set_disabled');?></label>
</td></tr>
<tr>
<th><?php _e('set_autotag');?>:<br/><span class="descr"><?php _e('set_autotag_descr');?></span></th>
<td>
@ -169,6 +184,12 @@ function selectOptionsA($a, $value, $default=null)
<label><input type="radio" name="session" value="files" <?php if(_c('session')=='files') echo 'checked="checked"'; ?> /><?php _e('set_sessions_files');?></label> <span class="descr">(&lt;mytinytodo_dir&gt;/tmp/sessions)</span>
</td></tr>
<tr>
<th><?php _e('set_timezone');?>:</th>
<td>
<select name="timezone"><?php echo selectOptions(timezoneIdentifiers(), _c('timezone')); ?></select>
</td></tr>
<tr>
<th><?php _e('set_firstdayofweek');?>:</th>
<td>