diff --git a/README.md b/README.md index 4fb0c67..9a3b527 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ myTinyTodo -Original website - http://www.mytinytodo.net/ \ No newline at end of file +Original website - http://www.mytinytodo.net/ diff --git a/src/COPYRIGHT b/src/COPYRIGHT index 6e9344e..6763173 100644 --- a/src/COPYRIGHT +++ b/src/COPYRIGHT @@ -41,4 +41,4 @@ Url: https://github.com/furf/jquery-ui-touch-punch Copyright: Copyright 2011–2014, Dave Furfero License: Dual licensed under the MIT or GPL Version 2 licenses. -This software contains images by 3d-parties. See files content/themes/default/images/COPYRIGHT and content/themes/ie8/images/COPYRIGHT for details. \ No newline at end of file +This software contains images by 3d-parties. See files content/themes/default/images/COPYRIGHT and content/themes/ie8/images/COPYRIGHT for details. diff --git a/src/ajax.php b/src/ajax.php index e81a055..a1b86fd 100644 --- a/src/ajax.php +++ b/src/ajax.php @@ -4,7 +4,7 @@ This file is part of myTinyTodo. (C) Copyright 2009-2010 Max Pozdeev Licensed under the GNU GPL v2 license. See file COPYRIGHT for details. -*/ +*/ set_error_handler('myErrorHandler'); set_exception_handler('myExceptionHandler'); @@ -46,7 +46,7 @@ elseif(isset($_GET['loadTasks'])) if (_get('compl') == 0) { $sqlWhere .= ' AND compl=0'; } - + $tag = trim(_get('t')); if($tag != '') { @@ -87,7 +87,7 @@ elseif(isset($_GET['loadTasks'])) if (preg_match("|^#(\d+)$|", $s, $m)) $sqlWhere .= " AND {$db->prefix}todolist.id = ". (int)$m[1]; else $sqlWhere .= " AND (title LIKE ". $db->quoteForLike("%%%s%%",$s). " OR note LIKE ". $db->quoteForLike("%%%s%%",$s). ")"; } - + $sort = (int)_get('sort'); $sqlSort = "ORDER BY compl ASC, "; if($sort == 1) $sqlSort .= "prio DESC, ddn ASC, duedate ASC, ow ASC"; // byPrio @@ -524,7 +524,7 @@ elseif(isset($_GET['setHideList'])) $flag = (int)_post('hide'); $bitwise = ($flag == 0) ? 'taskview & ~4' : 'taskview | 4'; $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); - jsonExit(array('total'=>1)); + jsonExit(array('total'=>1)); } @@ -718,9 +718,9 @@ function parse_duedate($s) $d = (int)$ma[1]; $m = (int)$ma[2]; $y = (int)$ma[3]; } elseif(preg_match("|^(\d+)\.(\d+)\b|", $s, $ma)) { - $d = (int)$ma[1]; $m = (int)$ma[2]; + $d = (int)$ma[1]; $m = (int)$ma[2]; $a = explode(',', date('Y,m,d')); - if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; + if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; else $y = (int)$a[0]; } elseif(preg_match("|^(\d+)\/(\d+)\b|", $s, $ma)) @@ -731,7 +731,7 @@ function parse_duedate($s) $m = (int)$ma[1]; $d = (int)$ma[2]; } $a = explode(',', date('Y,m,d')); - if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; + if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; else $y = (int)$a[0]; } else return null; @@ -853,7 +853,7 @@ function moveTask($id, $listId) return false; $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=? AND compl=?", array($listId, $r['compl']?1:0)); - + $db->ex("BEGIN"); $db->ex("UPDATE {$db->prefix}tag2task SET list_id=? WHERE task_id=?", array($listId, $id)); $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=?, d_edited=? WHERE id=?", array($listId, $ow, time(), $id)); diff --git a/src/content/themes/default/index.php b/src/content/themes/default/index.php index 717d37b..5711ae8 100644 --- a/src/content/themes/default/index.php +++ b/src/content/themes/default/index.php @@ -103,18 +103,18 @@ $().ready(function(){
- - + +
+
- +
- +
@@ -282,7 +282,7 @@ $().ready(function(){ @@ -110,7 +110,7 @@ $().ready(function(){ - +
@@ -169,7 +169,7 @@ $().ready(function(){
- +
diff --git a/src/content/themes/ie8/mtt.js b/src/content/themes/ie8/mtt.js index d5645be..6fba1ca 100644 --- a/src/content/themes/ie8/mtt.js +++ b/src/content/themes/ie8/mtt.js @@ -4,7 +4,7 @@ if (window !== undefined && window.mytinytodo !== undefined) mytinytodo.prepareTaskStr = function(item, noteExp) { // — = — = — - var id = item.id; + var id = item.id; var prio = item.prio; return '
  • ' + @@ -25,7 +25,7 @@ if (window !== undefined && window.mytinytodo !== undefined) ''+ "
  • \n"; }; - + mytinytodo.filter.prepareTagHtml = function(tagId, tag, classes) { return '' + tag + ''; } diff --git a/src/content/themes/ie8/pda.css b/src/content/themes/ie8/pda.css index 95d7fe3..3e6bb84 100644 --- a/src/content/themes/ie8/pda.css +++ b/src/content/themes/ie8/pda.css @@ -20,7 +20,7 @@ h3 { margin-bottom:4px; padding:4px 0; } .task-actions { display:none; } .task-date { display:none; } .task-note-actions { display:block; padding-top:8px; } -.task-note-block { margin-left:0px; border-left:1px solid #777777; background:none; padding-left:4px; margin-top:1px; padding-top:0px; display:none; } +.task-note-block { margin-left:0px; border-left:1px solid #777777; background:none; padding-left:4px; margin-top:1px; padding-top:0px; display:none; } .task-note-area textarea { width:95%; } .task-middle { margin-right:0px; } diff --git a/src/content/themes/ie8/print.css b/src/content/themes/ie8/print.css index a55df63..14ebd34 100644 --- a/src/content/themes/ie8/print.css +++ b/src/content/themes/ie8/print.css @@ -1,7 +1,7 @@ html { height:0; } body { height:0; min-height:0; margin:0; } h2{ display: none; } -h3 { border-bottom:2px solid #777777; } +h3 { border-bottom:2px solid #777777; } #lists { display: none; } #toolbar { display: none; } .small-bar { display:none; } @@ -12,8 +12,8 @@ h3 { border-bottom:2px solid #777777; } #taskviewcontainer img { display:none; } #tasklist { list-style-type: decimal; list-style-position: outside; } -#tasklist li { padding-left:0px; margin-left:30px; border-bottom:none; padding-bottom: 8px; } -div.task-note-block { border-left:1px solid #777777; background:none; padding-left:5px; margin-top:5px; padding-top:0px; font-size:9pt; color:#333333; } +#tasklist li { padding-left:0px; margin-left:30px; border-bottom:none; padding-bottom: 8px; } +div.task-note-block { border-left:1px solid #777777; background:none; padding-left:5px; margin-top:5px; padding-top:0px; font-size:9pt; color:#333333; } .task-middle { margin-left:0px; margin-right:3px; } .task-left { display:none; } @@ -28,4 +28,4 @@ li.task-completed { opacity:1; } #tagcloudbtn { display:none; } .mtt-notes-showhide { display:none; } -#taskview img { display:none; } \ No newline at end of file +#taskview img { display:none; } diff --git a/src/content/themes/ie8/style.css b/src/content/themes/ie8/style.css index 1c82da6..600d23e 100644 --- a/src/content/themes/ie8/style.css +++ b/src/content/themes/ie8/style.css @@ -1,5 +1,5 @@ /* - This file is a part of myTinyTodo. + This file is a part of myTinyTodo. Copyright 2009-2010 Max Pozdeev */ @@ -49,7 +49,7 @@ a { color:#0000ff; cursor:pointer; text-decoration:underline; } .mtt-tab a { position:relative; margin:0; font-size:0.9em; font-weight:bold; text-decoration:none; text-align:center; white-space:nowrap; color:#444444; display:block; height:21px; padding:6px 6px 0px 2px; outline:none; vertical-align:top; } .mtt-tab a span { display:inline-block; min-width:75px; max-width:195px; cursor:pointer; padding:0; overflow:hidden; } .mtt-tab .list-action { display:none; float:left; position:absolute; top:6px; right:5px; width:15px; height:15px; background:transparent url(images/icons.gif) 0 0 no-repeat; cursor:pointer; } -.mtt-tab .list-action:hover, .mtt-tab .list-action.mtt-menu-button-active { background-position:-16px 0; } +.mtt-tab .list-action:hover, .mtt-tab .list-action.mtt-menu-button-active { background-position:-16px 0; } .mtt-tab.mtt-tabs-selected span { margin-right:16px; } .mtt-tab.mtt-tabs-selected .list-action { display:block; } .mtt-tab.mtt-tabs-selected { background:#ededed url(images/corner_right.gif) no-repeat top right; border-left:1px solid #ededed; } @@ -57,7 +57,7 @@ a { color:#0000ff; cursor:pointer; text-decoration:underline; } .mtt-tabs.mtt-tabs-only-one li { display:none; } .mtt-tabs.mtt-tabs-only-one li.mtt-tabs-selected { display:block; } .mtt-tabs-hidden { display:none; } - + .mtt-tabs-alltasks { margin:1px 3px 0 3px; float:right; border-right:1px solid #ededed; background:#fbfbfb url(images/tab_hover.gif) no-repeat top left; } .mtt-tabs-alltasks.mtt-tab a { padding:6px 2px 0px 6px; } .mtt-tabs-alltasks.mtt-tab.mtt-tabs-selected { border-left:none; border-right:1px solid #ededed; background:#ededed url(images/corner_left.gif) no-repeat top left; } @@ -66,7 +66,7 @@ a { color:#0000ff; cursor:pointer; text-decoration:underline; } #tabs_buttons { float:right; padding-top:4px; - padding-bottom:2px; + padding-bottom:2px; padding-left:2px; padding-right:2px; border:1px solid #ededed; @@ -133,7 +133,7 @@ a { color:#0000ff; cursor:pointer; text-decoration:underline; } #htab_search { float:right; } #search { color:#444444; background:#fff; height:1.35em; padding:2px 18px; width:100%; margin-left:-38px; /*padding+border*/ - border:1px inset #F0F0F0; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; + border:1px inset #F0F0F0; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; } #search_close { display:none; } @@ -185,8 +185,8 @@ li.task-expanded .task-toggle { background-position:-80px -16px; } .duedate { color:#333333; padding:0px; padding-left:1px; margin-left:5px; } li.task-completed .duedate { /*font-size:0.8em;*/ display:none; } #tasklist li.soon .duedate { color:#008000; } -#tasklist li.today .duedate { color:#FF0000; } -#tasklist li.past .duedate { color:#A52A2A; } +#tasklist li.today .duedate { color:#FF0000; } +#tasklist li.past .duedate { color:#A52A2A; } li.task-completed .task-middle { color:#777777;} li.task-completed .task-through { text-decoration:line-through; } li.task-completed .task-title a { color:#777777; } @@ -206,7 +206,7 @@ li:hover a.taskactionbtn, a.taskactionbtn.mtt-menu-button-active { background-po #tasklist.filter-past li.past, #tasklist.filter-today li.today, #tasklist.filter-soon li.soon { display:block; } #tasklist.filter-past li.task-completed, #tasklist.filter-today li.task-completed, #tasklist.filter-soon li.task-completed { display:none; } -.task-note-block { margin-left:2px; color:#777777; background:url(images/page_white_text.png) left 2px no-repeat; +.task-note-block { margin-left:2px; color:#777777; background:url(images/page_white_text.png) left 2px no-repeat; padding-left:19px; padding-top:2px; min-height:16px; margin-top:2px; display:none; word-wrap:break-word; white-space:noraml; } li.task-expanded .task-note-block { display:block; } li.task-completed .task-note-block .task-note { text-decoration:line-through; } @@ -225,7 +225,7 @@ li.task-completed .task-note-block .task-note { text-decoration:line-through; } .prio-pos { background-color:#ff3333; color:#ffffff; } .prio-pos-1 { background-color:#ff7700; color:#ffffff; } .prio-zero { /*background-color:#dedede;*/ } -.task-prio.prio-zero { display:none; } +.task-prio.prio-zero { display:none; } .form-row { margin-top:8px; } .form-row .h { font-weight:bold; color:#333333; } @@ -251,7 +251,7 @@ a.mtt-back-button { font-size:0.8em; } .ui-autocomplete .ui-menu-item-wrapper.ui-state-active { background-color:#5373fc; background:linear-gradient(#5373fc, #3157f4); color:white; } -#priopopup { overflow: hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; padding:5px; } +#priopopup { overflow: hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; padding:5px; } #priopopup span { cursor:pointer; border:1px solid #f9f9f9; } #priopopup .prio-zero:hover { border-color:#dedede; } #priopopup .prio-neg:hover { border-color:#3377ff; } @@ -265,7 +265,7 @@ a.mtt-back-button { font-size:0.8em; } overflow: hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; padding:5px; width:100%; max-width:450px; margin:0px 7px 7px 7px; text-align:center; -moz-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -webkit-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -} +} #tagcloud .tag { margin:1px 0px; padding:2px; line-height:140%; color:black; } #tagcloud .tag:hover { background-color:#999988; color:white; } #tagcloud .w0 { font-size:80%; } @@ -285,11 +285,11 @@ a.mtt-back-button { font-size:0.8em; } #taskview { padding:2px; } -.ui-datepicker { width:190px; z-index:202; border: 1px solid #cccccc; background: #ffffff; display:none; padding:2px; - -moz-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -webkit-box-shadow:1px 2px 5px rgba(0,0,0,0.5); box-shadow:1px 2px 5px rgba(0,0,0,0.5); +.ui-datepicker { width:190px; z-index:202; border: 1px solid #cccccc; background: #ffffff; display:none; padding:2px; + -moz-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -webkit-box-shadow:1px 2px 5px rgba(0,0,0,0.5); box-shadow:1px 2px 5px rgba(0,0,0,0.5); -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; } -.ui-datepicker-trigger { cursor:pointer; vertical-align:text-bottom; margin-left:1px; } +.ui-datepicker-trigger { cursor:pointer; vertical-align:text-bottom; margin-left:1px; } .ui-datepicker-calendar { width:100%; border-collapse:collapse; } .ui-datepicker-calendar thead th { text-align:center; padding:0px; font-size:0.9em; } .ui-datepicker-calendar tbody td { text-align:right; padding:1px; } @@ -310,22 +310,22 @@ a.mtt-back-button { font-size:0.8em; } cursor:pointer; border:1px solid transparent; } -.mtt-menu-button:hover, .mtt-menu-button.mtt-menu-button-active { +.mtt-menu-button:hover, .mtt-menu-button.mtt-menu-button-active { border:1px solid #ccc; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; } -.mtt-menu-container { +.mtt-menu-container { overflow:hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; padding:2px 0px; - -moz-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -webkit-box-shadow:1px 2px 5px rgba(0,0,0,0.5); box-shadow:1px 2px 5px rgba(0,0,0,0.5); + -moz-box-shadow:1px 2px 5px rgba(0,0,0,0.5); -webkit-box-shadow:1px 2px 5px rgba(0,0,0,0.5); box-shadow:1px 2px 5px rgba(0,0,0,0.5); -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; margin:0px 7px 7px 0px; /* for shadows */ -} +} .mtt-menu-container ul { list-style: none; padding:0; margin:0; } .mtt-menu-container li { margin:1px 0px; cursor:default; color:#000; white-space:nowrap; padding:0.15em 0px; padding-left:24px; padding-right:18px; position:relative; } -.mtt-menu-container li:hover, .mtt-menu-container li.mtt-menu-item-active { +.mtt-menu-container li:hover, .mtt-menu-container li.mtt-menu-item-active { background-color:#316AC5; - color:white; + color:white; background:-moz-linear-gradient(#5373fc, #3157f4); background:-webkit-gradient(linear, left top, left bottom, from(#5373fc), to(#3157f4)); } diff --git a/src/content/themes/ie8/style_rtl.css b/src/content/themes/ie8/style_rtl.css index df489f2..a1466fa 100644 --- a/src/content/themes/ie8/style_rtl.css +++ b/src/content/themes/ie8/style_rtl.css @@ -30,4 +30,4 @@ h2 { float:right; padding-left:10px; padding-right:0px; } #taskedit-date { float:left; } #page_taskedit .form-row-short { float:right; margin-left:12px; margin-right:0; } .task-prio { float:right; margin-left:4px; margin-right:0; } -.alltags-cell { padding-left:0; padding-right:5px; } \ No newline at end of file +.alltags-cell { padding-left:0; padding-right:5px; } diff --git a/src/export.php b/src/export.php index 5a6a65c..9809435 100644 --- a/src/export.php +++ b/src/export.php @@ -25,13 +25,13 @@ else $sqlSort .= "ow ASC"; $data = array(); $q = $db->dq("SELECT *, duedate IS NULL AS ddn FROM {$db->prefix}todolist WHERE list_id=$listId $sqlSort"); -while($r = $q->fetch_assoc($q)) +while($r = $q->fetch_assoc($q)) { - $data[] = $r; + $data[] = $r; } $format = _get('format'); - + if($format == 'ical') printICal($listData, $data); else printCSV($listData, $data); @@ -94,7 +94,7 @@ function printICal($listData, $data) # Apple's iCal priorities: low-9, medium-5, high-1 if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']]; $a[] = "X-MTT-PRIORITY:". $r['prio']; - + $descr = array(); if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']); if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note']; @@ -112,7 +112,7 @@ function printICal($listData, $data) # events foreach($data as $r) { - if(!$r['duedate'] || $r['compl']) continue; # skip tasks completed and without duedate + if(!$r['duedate'] || $r['compl']) continue; # skip tasks completed and without duedate $a = array(); $a[] = "BEGIN:VEVENT"; $a[] = "UID:_". $r['uuid']; # do not duplicate VTODO UID diff --git a/src/feed.php b/src/feed.php index 8083e9b..59d6c77 100644 --- a/src/feed.php +++ b/src/feed.php @@ -47,7 +47,7 @@ htmlarray_ref($listData); $data = array(); $q = $db->dq("SELECT * FROM {$db->prefix}todolist WHERE list_id=$listId $sqlWhere ORDER BY ". $listData['_uid_field'] ." DESC LIMIT 100"); -while($r = $q->fetch_assoc($q)) +while($r = $q->fetch_assoc($q)) { if($r['prio'] > 0) $r['prio'] = '+'.$r['prio']; $a = array(); diff --git a/src/includes/class.db.mysql.php b/src/includes/class.db.mysql.php index 6fe1520..4ccc647 100644 --- a/src/includes/class.db.mysql.php +++ b/src/includes/class.db.mysql.php @@ -3,7 +3,7 @@ /* (C) Copyright 2009,2019 Max Pozdeev Licensed under the GNU GPL v2 license. See file COPYRIGHT for details. -*/ +*/ // ---------------------------------------------------------------------------- // class DatabaseResult_Mysql @@ -82,8 +82,8 @@ class Database_Mysql function last_insert_id() { return mysqli_insert_id($this->dbh); - } - + } + function error() { return mysqli_error($this->dbh); diff --git a/src/includes/class.db.sqlite3.php b/src/includes/class.db.sqlite3.php index f2572ce..950e65d 100644 --- a/src/includes/class.db.sqlite3.php +++ b/src/includes/class.db.sqlite3.php @@ -22,7 +22,7 @@ class DatabaseResult_Sqlite3 $r = $this->parent->dbh->exec($query); if($r === false) { $ei = $this->parent->dbh->errorInfo(); - throw new Exception("SQLSTATE[$ei[0]] [$ei[1]] $ei[2]"); + throw new Exception("SQLSTATE[$ei[0]] [$ei[1]] $ei[2]"); } $this->parent->affected = $r; } @@ -91,13 +91,13 @@ class Database_Sqlite3 if(sizeof($res) > 1) return $res; else return $res[0]; } - + function dq($query, $p = NULL) { return $this->_dq($query, $p); } - /* + /* for resultless queries like INSERT,UPDATE */ function ex($query, $p = NULL) diff --git a/src/includes/class.lang.php b/src/includes/class.lang.php index bfe22ec..6f0d28e 100644 --- a/src/includes/class.lang.php +++ b/src/includes/class.lang.php @@ -11,20 +11,20 @@ class Lang protected $code = 'en'; protected $default = 'en'; protected $strings; - + public static function instance() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; } - return self::$instance; + return self::$instance; } - + public static function loadLangOrDie($code, $die = 1) { $lang = self::instance(); - + //check if json file exists if ( self::langExists($code) ) { $jsonString = file_get_contents( self::$langDir. "{$code}.json" ); @@ -39,22 +39,22 @@ class Lang die("Language file not found ($code.json)"); } } - + public static function loadLang($code) { self::loadLangOrDie($code, 0); } - + public static function langExists($code) { return file_exists(self::$langDir. $code. '.json'); } - + function loadJsonString($code, $jsonString) { $this->code = $code; $json = json_decode($jsonString, true); - + //load default language if ( $code != $this->default ) { $this->loadDefaultStrings(); @@ -64,7 +64,7 @@ class Lang $this->strings = $json; } } - + function loadDefaultStrings() { if ( ! self::langExists($this->default) ) { @@ -73,7 +73,7 @@ class Lang $defStr = file_get_contents($this->langDir(). "{$this->default}.json"); $this->strings = json_decode($defStr, true); } - + function get($key) { if ( isset($this->strings[$key]) ) { @@ -81,7 +81,7 @@ class Lang } return $key; } - + function rtl() { if ( isset($this->strings['_rtl']) ) { @@ -89,7 +89,7 @@ class Lang } return 0; } - + function makeJS($pretty = 0) { $a = array(); @@ -97,7 +97,7 @@ class Lang $a['daysLong'] = $this->get('days_long'); $a['monthsShort'] = $this->get('months_short'); $a['monthsLong'] = $this->get('months_long'); - + $this->fillWithValues($a, [ 'confirmDelete', 'confirmLeave', @@ -120,26 +120,26 @@ class Lang 'alltasks' ]); $a['_rtl'] = $this->rtl() ? 1 : 0; - + $opts = JSON_UNESCAPED_UNICODE; if ($pretty) { $opts |= JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES; } return json_encode($a, $opts); } - + protected function fillWithValues(array &$a, array $keys) { foreach ( $keys as $key ) { $a[$key] = $this->get($key); } } - + function langDir() { return self::$langDir; } - + function langCode() { return $this->code; diff --git a/src/includes/common.php b/src/includes/common.php index 88b194c..d2309f1 100644 --- a/src/includes/common.php +++ b/src/includes/common.php @@ -35,14 +35,14 @@ function stop_gpc(&$arr) if (!is_array($arr)) { return 1; } - + // Since PHP v5.4.0 magic quotes feature was removed from PHP // In PHP v7.4 get_magic_quotes_gpc is deprecated // TODO: do not use get_magic_quotes_gpc() and stop_gpc() if (!@get_magic_quotes_gpc()) { return 1; } - + reset($arr); foreach ($arr as $k=>$v) { @@ -74,7 +74,7 @@ function _get($param,$defvalue = '') else { return $_GET[$param]; } -} +} function _server($param, $defvalue = '') { @@ -128,7 +128,7 @@ class Config elseif(isset(self::$params[$key])) return self::$params[$key]['default']; else return null; } - + public static function getUrl($key) { $url = ''; @@ -162,7 +162,7 @@ class Config if($f === false) throw new Exception("Error while saving config file"); fwrite($f, ""); fclose($f); -/* +/* //Reset Zend OPcache //opcache_get_status() sometimes crashes //TODO: save config in database! @@ -218,7 +218,7 @@ function escapeTags($s) $c1 = chr(1); $c2 = chr(2); $s = preg_replace("~([\s\S]*?)~i", "${c1}b${c2}\$1${c1}/b${c2}", $s); - $s = preg_replace("~([\s\S]*?)~i", "${c1}i${c2}\$1${c1}/i${c2}", $s); + $s = preg_replace("~([\s\S]*?)~i", "${c1}i${c2}\$1${c1}/i${c2}", $s); $s = preg_replace("~([\s\S]*?)~i", "${c1}u${c2}\$1${c1}/u${c2}", $s); $s = preg_replace("~([\s\S]*?)~i", "${c1}s${c2}\$1${c1}/s${c2}", $s); $s = str_replace(array($c1, $c2), array('<','>'), htmlspecialchars($s)); @@ -253,7 +253,7 @@ class DBConnection $c = 'DBConnection'; self::$instance = new $c; } - return self::$instance; + return self::$instance; } } diff --git a/src/includes/mytinytodo.js b/src/includes/mytinytodo.js index d56c46d..e7bb9c8 100644 --- a/src/includes/mytinytodo.js +++ b/src/includes/mytinytodo.js @@ -5,7 +5,7 @@ */ (function(){ - + "use strict"; var taskList = new Array(), taskOrder = new Array(); @@ -23,7 +23,7 @@ var tabLists = { _alltasks: {}, clear: function(){ this._lists = {}; this._length = 0; this._order = []; - this._alltasks = { id:-1, showCompl:0, sort:3, name:_mtt.lang.get('alltasks') }; + this._alltasks = { id:-1, showCompl:0, sort:3, name:_mtt.lang.get('alltasks') }; }, length: function(){ return this._length; }, exists: function(id){ if(this._lists[id] || id==-1) return true; else return false; }, @@ -81,7 +81,7 @@ var mytinytodo = window.mytinytodo = _mtt = { if(this.__lang[v]) return this.__lang[v]; else return v; }, - + init: function(lang) { this.__lang = lang; @@ -90,21 +90,21 @@ var mytinytodo = window.mytinytodo = _mtt = { this.monthsShort = this.__lang.monthsShort; this.monthsLong = this.__lang.monthsLong; }, - + isRTL: function() { return this.get('_rtl') > 0 ? true : false; } }, - pages: { + pages: { current: { page:'tasks', pageClass:'' }, prev: [] }, - + curList: function(){ return curList; }, - + flag: flag, // procs @@ -130,7 +130,7 @@ var mytinytodo = window.mytinytodo = _mtt = { else { this.homeUrl = this.mttUrl; } - + jQuery.extend(this.options, options); flag.needAuth = options.needAuth ? true : false; @@ -159,7 +159,7 @@ var mytinytodo = window.mytinytodo = _mtt = { submitNewTask(this); return false; }); - + $('#newtask_submit').mousedown(function(e){ e.preventDefault(); //keep the focus in #task $('#newtask_form').submit(); @@ -169,7 +169,7 @@ var mytinytodo = window.mytinytodo = _mtt = { showEditForm(1); return false; }); - + $('#task').keydown(function(event){ if(event.keyCode == 27) { $(this).val(''); @@ -228,7 +228,7 @@ var mytinytodo = window.mytinytodo = _mtt = { $('#mtt-tag-filters').on('click', '.mtt-filter-close', function(){ cancelTagFilter($(this).attr('tagid')); }); - + $('#mtt-tag-toolbar-close').click(function(){ cancelTagFilter(0); }); @@ -254,7 +254,7 @@ var mytinytodo = window.mytinytodo = _mtt = { addFilterTag( $(this).attr('tag'), $(this).attr('tagid'), (event.metaKey || event.ctrlKey ? true : false) ); if(_mtt.menus.tagcloud) _mtt.menus.tagcloud.close(); return false; - }); + }); $('#mtt-notes-show').click(function(){ toggleAllNotes(1); @@ -275,7 +275,7 @@ var mytinytodo = window.mytinytodo = _mtt = { else if(this.id == 'view_soon') setTaskview('soon'); }); - + // Tabs $('#lists').on('click', 'li.mtt-tab', function(event){ if(event.metaKey || event.ctrlKey) { @@ -286,7 +286,7 @@ var mytinytodo = window.mytinytodo = _mtt = { tabSelect(this); return false; }); - + $('#list_all').click(function(event){ if(event.metaKey || event.ctrlKey) { // hide the tab @@ -301,7 +301,7 @@ var mytinytodo = window.mytinytodo = _mtt = { listMenu(this); return false; //stop bubble to tab click }); - + $('#list_all .list-action').click(function(event){ listMenu(this); return false; //stop bubble to tab click @@ -348,7 +348,7 @@ var mytinytodo = window.mytinytodo = _mtt = { addEditTag($(this).attr('tag')); return false; }); - + $("#duedate").datepicker({ dateFormat: _mtt.duedatepickerformat(), firstDay: _mtt.options.firstdayofweek, @@ -363,7 +363,7 @@ var mytinytodo = window.mytinytodo = _mtt = { monthNames:_mtt.lang.monthsLong, isRTL: _mtt.lang.isRTL() }); - + function ac_split( val ) { return val.split( /,\s*/ ); } @@ -406,12 +406,12 @@ var mytinytodo = window.mytinytodo = _mtt = { // tasklist handlers $("#tasklist").bind("click", tasklistClick); - + $('#tasklist').on('dblclick', 'li', function(){ //clear selection if(document.selection && document.selection.empty && document.selection.createRange().text) document.selection.empty(); else if(window.getSelection) window.getSelection().removeAllRanges(); - + var li = findParentNode(this, 'LI'); if(li && li.id) { var id = li.id.split('_',2)[1]; @@ -484,14 +484,14 @@ var mytinytodo = window.mytinytodo = _mtt = { cancel: 'span,input,a,textarea', delay: 150, start: tasklistSortStart, - update: tasklistSortUpdated, + update: tasklistSortUpdated, placeholder: 'mtt-task-placeholder', cursor: 'grabbing' }); - + if (options.touchDevice) { $("#tasklist").disableSelection(); - $("#tasklist").sortable('option', { + $("#tasklist").sortable('option', { axis: 'y', delay: 0, cancel: 'input', @@ -500,7 +500,7 @@ var mytinytodo = window.mytinytodo = _mtt = { $('#cmenu_note').hide(); } - $("#lists ul").sortable({delay:150, update:listOrderChanged}); + $("#lists ul").sortable({delay:150, update:listOrderChanged}); this.applySingletab(); @@ -519,8 +519,8 @@ var mytinytodo = window.mytinytodo = _mtt = { if(request.status == 0) errtxt = 'Bad connection'; else if(request.status != 200) errtxt = 'HTTP: '+request.status+'/'+request.statusText; else errtxt = request.responseText; - flashError(_mtt.lang.get('error'), errtxt); - }); + flashError(_mtt.lang.get('error'), errtxt); + }); // Error Message details @@ -552,7 +552,7 @@ var mytinytodo = window.mytinytodo = _mtt = { saveSettings(this); return false; }); - + $(document).on('click', '.mtt-back-button', function(){ _mtt.pageBack(); this.blur(); return false; } ); $(window).bind('beforeunload', function() { @@ -579,13 +579,13 @@ var mytinytodo = window.mytinytodo = _mtt = { this.addAction('listAdded', slmenuOnListAdded); this.addAction('listSelected', slmenuOnListSelected); this.addAction('listHidden', slmenuOnListHidden); - + //History if (this.options.history) { window.onpopstate = historyOnPopState; this.addAction('listSelected', historyListSelected); } - + this.doAction( 'init' ); return this; @@ -613,15 +613,15 @@ var mytinytodo = window.mytinytodo = _mtt = { setOptions: function(opts) { jQuery.extend(this.options, opts); }, - + run: function() { var path = this.parseAnchor(); - + if (flag.firstLoad) { updateAccessStatus(); } - + if (path.settings) { this.pages.current.onBack = function(){ this.loadLists(); } showSettings(); @@ -640,9 +640,9 @@ var mytinytodo = window.mytinytodo = _mtt = { } $('#page_tasks').hide(); $('#tasklist').html(''); - + tabLists.clear(); - + this.db.loadLists(null, function(res) { var ti = ''; @@ -662,13 +662,13 @@ var mytinytodo = window.mytinytodo = _mtt = { break; } } - + // open all tasks tab if(_mtt.options.openList == -1) openListId = -1; - + // or open first if all list are hidden if(!openListId) openListId = res.list[0].id; - + $.each(res.list, function(i,item){ tabLists.add(item); ti += '
  • '+ @@ -676,7 +676,7 @@ var mytinytodo = window.mytinytodo = _mtt = { '
  • '; }); } - + if(openListId) { $('#mtt_body').removeClass('no-lists'); $('.mtt-need-list').removeClass('mtt-item-disabled'); @@ -686,7 +686,7 @@ var mytinytodo = window.mytinytodo = _mtt = { $('#mtt_body').addClass('no-lists'); $('.mtt-need-list').addClass('mtt-item-disabled'); } - + if (_mtt.options.openList && openListId != _mtt.options.openList) { //TODO: handle unknown list } @@ -706,7 +706,7 @@ var mytinytodo = window.mytinytodo = _mtt = { duedatepickerformat: function() { if(!this.options.duedatepickerformat) return 'yy-mm-dd'; - + var s = this.options.duedatepickerformat.replace(/(.)/g, function(t,s) { switch(t) { case 'Y': return 'yy'; @@ -730,7 +730,7 @@ var mytinytodo = window.mytinytodo = _mtt = { { flashError(this.lang.get('denied')); }, - + pageSet: function(page, pageClass) { var prev = this.pages.current; @@ -739,7 +739,7 @@ var mytinytodo = window.mytinytodo = _mtt = { this.pages.current = {page:page, pageClass:pageClass}; showhide($('#page_'+ this.pages.current.page).addClass('mtt-page-'+ this.pages.current.pageClass), $('#page_'+ prev.page)); }, - + pageBack: function() { if(this.pages.current.page == 'tasks') return false; @@ -749,12 +749,12 @@ var mytinytodo = window.mytinytodo = _mtt = { $(window).scrollTop(this.pages.current.lastScrollTop); if (this.pages.current.onBack) this.pages.current.onBack.call(this); }, - + applySingletab: function(yesno) { if(yesno == null) yesno = this.options.singletab; else this.options.singletab = yesno; - + if(yesno) { $('#lists .mtt-tabs').addClass('mtt-tabs-only-one'); $("#lists ul").sortable('disable'); @@ -764,7 +764,7 @@ var mytinytodo = window.mytinytodo = _mtt = { $("#lists ul").sortable('enable'); } }, - + filter: { _filters: [], clear: function() { @@ -813,7 +813,7 @@ var mytinytodo = window.mytinytodo = _mtt = { return '' + tag + ''; } }, - + parseAnchor: function() { if(location.hash == '') return false; @@ -821,7 +821,7 @@ var mytinytodo = window.mytinytodo = _mtt = { var a = h.split("/"); var p = {}; var s = ''; - + for(var i=0; i.mtt-tabs-selected>a').attr('title', item.name).find('span').html(item.name); mytinytodo.doAction('listRenamed', item); }); @@ -901,7 +901,7 @@ function renameCurList() function deleteCurList() { if (!curList) return false; - mttConfirm( _mtt.lang.get('deleteList'), function() + mttConfirm( _mtt.lang.get('deleteList'), function() { _mtt.db.request('deleteList', {list:curList.id}, function(json){ if (!parseInt(json.total)) return; @@ -977,24 +977,24 @@ function prepareTaskBlocks(item) { var id = item.id; return ''+ - '
    ' + + '
    ' + '
    ' + - '' + + '' + "
    \n" + - - '
    ' + - + + '
    ' + + '
    ' + - '
    ' + - preparePrio(item.prio,id) + + '
    ' + + preparePrio(item.prio,id) + '' + prepareHtml(item.title) + ' ' + (curList.id == -1 ? ''+ tabLists.get(item.listId).name +'' : '') + - prepareTagsStr(item) + + prepareTagsStr(item) + ''+item.dateInlineTitle+'' + '
    ' + '
    ' + prepareDueDate(item) + prepareCompletedDate(item) + "
    " + - '
    ' + - + '
    ' + + '
    ' + '
    '+prepareHtml(item.note)+'
    ' + '
    '+ @@ -1061,7 +1061,7 @@ _mtt.prepareDueDate = prepareDueDate; function prepareCompletedDate(item) { // — = — = — - return '' + + return '' + '' + item.dateInline + '—' + '' + item.dateCompletedInline + '' + ''; @@ -1084,7 +1084,7 @@ function submitNewTask(form) changeTaskOrder(item.id); $('#taskrow_'+item.id).effect("highlight", {color:_mtt.theme.newTaskFlashColor}, 2000); refreshTaskCnt(); - }); + }); flag.tagsChanged = true; return false; }; @@ -1096,7 +1096,7 @@ function changeTaskOrder(id) if(taskOrder.length < 2) return; var oldOrder = taskOrder.slice(); // sortByHand - if(curList.sort == 0) taskOrder.sort( function(a,b){ + if(curList.sort == 0) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; return taskList[a].ow-taskList[b].ow }); @@ -1105,57 +1105,57 @@ function changeTaskOrder(id) if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; - return taskList[a].ow-taskList[b].ow; + return taskList[a].ow-taskList[b].ow; }); // sortByPrio (reverse) else if(curList.sort == 101) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].prio != taskList[b].prio) return taskList[a].prio-taskList[b].prio; if(taskList[a].dueInt != taskList[b].dueInt) return taskList[b].dueInt-taskList[a].dueInt; - return taskList[b].ow-taskList[a].ow; - }); + return taskList[b].ow-taskList[a].ow; + }); // sortByDueDate else if(curList.sort == 2) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; - return taskList[a].ow-taskList[b].ow; + return taskList[a].ow-taskList[b].ow; }); // sortByDueDate (reverse) else if(curList.sort == 102) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dueInt != taskList[b].dueInt) return taskList[b].dueInt-taskList[a].dueInt; if(taskList[a].prio != taskList[b].prio) return taskList[a].prio-taskList[b].prio; - return taskList[b].ow-taskList[a].ow; - }); + return taskList[b].ow-taskList[a].ow; + }); // sortByDateCreated else if(curList.sort == 3) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dateInt != taskList[b].dateInt) return taskList[a].dateInt-taskList[b].dateInt; if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; - return taskList[a].ow-taskList[b].ow; + return taskList[a].ow-taskList[b].ow; }); // sortByDateCreated (reverse) else if(curList.sort == 103) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dateInt != taskList[b].dateInt) return taskList[b].dateInt-taskList[a].dateInt; if(taskList[a].prio != taskList[b].prio) return taskList[a].prio-taskList[b].prio; - return taskList[b].ow-taskList[a].ow; + return taskList[b].ow-taskList[a].ow; }); // sortByDateModified else if(curList.sort == 4) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dateEditedInt != taskList[b].dateEditedInt) return taskList[a].dateEditedInt-taskList[b].dateEditedInt; if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; - return taskList[a].ow-taskList[b].ow; + return taskList[a].ow-taskList[b].ow; }); // sortByDateModified (reverse) else if(curList.sort == 104) taskOrder.sort( function(a,b){ if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; if(taskList[a].dateEditedInt != taskList[b].dateEditedInt) return taskList[b].dateEditedInt-taskList[a].dateEditedInt; if(taskList[a].prio != taskList[b].prio) return taskList[a].prio-taskList[b].prio; - return taskList[b].ow-taskList[a].ow; - }); + return taskList[b].ow-taskList[a].ow; + }); else return; if(oldOrder.toString() == taskOrder.toString()) return; if(id && taskList[id]) @@ -1222,7 +1222,7 @@ function setSort(v, init) curList.sort = v; if(v == 0 && !flag.readOnly) $("#tasklist").sortable('enable'); else $("#tasklist").sortable('disable'); - + if(!init) { changeTaskOrder(); @@ -1314,14 +1314,14 @@ function tabSelect(elementOrId) flashError(_mtt.lang.get('denied'), id); return; } - + var prevList = curList; curList = tabLists.get(id); document.title = curList.name + ' - ' + _mtt.options.title; - + $('#lists .mtt-tabs-selected').removeClass('mtt-tabs-selected'); $('#list_all').removeClass('mtt-tabs-selected'); - + if(id == -1) { $('#list_all').addClass('mtt-tabs-selected').removeClass('mtt-tabs-hidden'); $('#listmenucontainer .mtt-need-real-list').addClass('mtt-item-hidden'); @@ -1330,7 +1330,7 @@ function tabSelect(elementOrId) $('#list_'+id).addClass('mtt-tabs-selected').removeClass('mtt-tabs-hidden'); $('#listmenucontainer .mtt-need-real-list').removeClass('mtt-item-hidden'); } - + if(prevList.id != id) { if(id == -1) $('#mtt_body').addClass('show-all-tasks'); @@ -1338,7 +1338,7 @@ function tabSelect(elementOrId) if(filter.search != '') liveSearchToggle(0, 1); mytinytodo.doAction('listSelected', tabLists.get(id)); } - + if(curList.hidden) { curList.hidden = false; if(curList.id > 0) _mtt.db.request('setHideList', {list:curList.id, hide:0}); @@ -1426,8 +1426,8 @@ function completeTask(id, ch) } else if(curList.showCompl) { $('#taskrow_'+item.id).replaceWith(_mtt.prepareTaskStr(taskList[id])); - $('#taskrow_'+id).fadeOut('fast', function(){ - changeTaskOrder(id); + $('#taskrow_'+id).fadeOut('fast', function(){ + changeTaskOrder(id); $(this).effect("highlight", {color:_mtt.theme.editTaskFlashColor}, 'normal', function(){$(this).css('display','')}); }); } @@ -1582,7 +1582,7 @@ function toggleEditAllTags(show) function fillEditAllTags() { var a = []; - for(var i=tagsList.length-1; i>=0; i--) { + for(var i=tagsList.length-1; i>=0; i--) { a.push(''+tagsList[i].tag+''); } $('#alltags .tags-list').html(a.join(', ')); @@ -1592,7 +1592,7 @@ function fillEditAllTags() function addEditTag(tag) { var v = $('#edittags').val(); - if(v == '') { + if(v == '') { $('#edittags').val(tag); return; } @@ -1644,7 +1644,7 @@ function liveSearchToggle(toSearch, dontLoad) $('#search_close').hide(); if(!dontLoad) loadTasks(); } - + $('#search').blur(); } }; @@ -1748,7 +1748,7 @@ function mttMenu(container, options) this.showTimer = null; this.ts = (new Date).getTime(); this.container.mttmenu = this.ts; - + if (!this.options.hasOwnProperty('isRTL')) { this.options.isRTL = ($('body').css('direction') == 'rtl') ? true : false; } @@ -1757,7 +1757,7 @@ function mttMenu(container, options) } if (!this.options.hasOwnProperty('adjustWidth')) { this.options.adjustWidth = true; - } + } this.$container.find('li').click(function(){ var r = menu.onclick(this, menu); @@ -1802,7 +1802,7 @@ function mttMenu(container, options) if(!submenu || menu.curSubmenu == submenu && menu.curSubmenu.isOpen) return; - + menu.showTimer = setTimeout(function(){ menu.curSubmenu = submenu; submenu.showSub(); @@ -1848,7 +1848,7 @@ function mttMenu(container, options) this.hide(); $(this.caller).removeClass('mtt-menu-button-active'); $(document).unbind('mousedown.mttmenuclose'); - + // onClose trigger if(this.options.onClose && this.options.onClose.call) { this.options.onClose.call(this); @@ -1865,7 +1865,7 @@ function mttMenu(container, options) $(document).triggerHandler('mousedown.mttmenuclose'); //close any other open menu this.caller = caller; var $caller = $(caller); - + // beforeShow trigger if(this.options.beforeShow && this.options.beforeShow.call) { this.options.beforeShow.call(this); @@ -1891,16 +1891,16 @@ function mttMenu(container, options) if (x > x2) { x = x2; //move left if container overflows right edge this.$container.addClass('mtt-right-adjusted'); - } + } if (x < 0) { x = 0; //do not cross left edge this.$container.addClass('mtt-left-adjusted'); - } - + } + var y = offset.top + caller.offsetHeight - 1; if(y + this.$container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = offset.top - this.$container.outerHeight(); if(y<0) y=0; - + this.$container.css({ position: 'absolute', top: y, left: x, width:this.$container.width() /*, 'min-width': $caller.width()*/ }).show(); var menu = this; $(document).bind('mousedown.mttmenuclose', function(e){ menu.close(e) }); @@ -1936,15 +1936,15 @@ function mttMenu(container, options) x = offset.left - containerWidth - 1; } if (x < 0) { - x = 0; + x = 0; this.$container.addClass('mtt-left-adjusted'); - } + } } - + var y = offset.top + this.parent.$container.offset().top-this.parent.$container.find('li:first').offset().top; if(y + this.$container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = $(window).height() + $(document).scrollTop()- this.$container.outerHeight(true) - 1; if(y<0) y=0; - + this.$container.css({ position: 'absolute', top: y, left: x, width:this.$container.width() /*, 'min-width': this.$caller.outerWidth()*/ }).show(); this.isOpen = true; }; @@ -2113,7 +2113,7 @@ function showCompletedToggle() function clearCompleted() { if (!curList) return false; - mttConfirm( _mtt.lang.get('clearCompleted'), function() + mttConfirm( _mtt.lang.get('clearCompleted'), function() { _mtt.db.request('clearCompletedInList', {list:curList.id}, function(json){ if(!parseInt(json.total)) return; @@ -2240,7 +2240,7 @@ function hideTab(listId) if(!id) return; listId = parseInt(id.split('_', 2)[1]); } - + if(!tabLists.get(listId)) return false; // if we hide current tab @@ -2263,14 +2263,14 @@ function hideTab(listId) else { $('#list_'+listId).addClass('mtt-tabs-hidden').removeClass('mtt-tabs-selected'); } - + tabLists.get(listId).hidden = true; - + if(listId > 0) { _mtt.db.request('setHideList', {list:listId, hide:1}); _mtt.doAction('listHidden', tabLists.get(listId)); } - + if(listIdToSelect) { tabSelect(listIdToSelect); } @@ -2385,7 +2385,7 @@ function logout() window.location.reload(); }, 'json'); return false; -} +} /* @@ -2395,7 +2395,7 @@ function logout() function showSettings() { if(_mtt.pages.current.page == 'ajax' && _mtt.pages.current.pageClass == 'settings') return false; - $('#page_ajax').load(_mtt.mttUrl+'settings.php?ajax=yes',null,function(){ + $('#page_ajax').load(_mtt.mttUrl+'settings.php?ajax=yes',null,function(){ //showhide($('#page_ajax').addClass('mtt-page-settings'), $('#page_tasks')); _mtt.pageSet('ajax','settings'); }) @@ -2406,7 +2406,7 @@ function saveSettings(frm) { if(!frm) return false; var params = { save:'ajax' }; - $(frm).find("input:text,input:password,input:checked,select").filter(":enabled").each(function() { params[this.name || '__'] = this.value; }); + $(frm).find("input:text,input:password,input:checked,select").filter(":enabled").each(function() { params[this.name || '__'] = this.value; }); $(frm).find(":submit").attr('disabled','disabled').blur(); $.post(_mtt.mttUrl+'settings.php', params, function(json){ if(json.saved) { @@ -2416,7 +2416,7 @@ function saveSettings(frm) }, 1000); } }, 'json'); -} +} /* @@ -2427,7 +2427,7 @@ function mttConfirm(msg, callbackOk, callbackCancel) { var r = confirm(msg); if (r) { - if (typeof callbackOk === 'function') + if (typeof callbackOk === 'function') callbackOk(); } else { @@ -2440,7 +2440,7 @@ function mttPrompt(msg, defaultValue, callbackOk, callbackCancel) { var r = prompt(msg, defaultValue); if (r !== null) { - if (typeof callbackOk === 'function') + if (typeof callbackOk === 'function') callbackOk(r); } else { @@ -2459,7 +2459,7 @@ function historyListSelected(list) flag.historySkip = false; return; } - + if (flag.firstLoad) { history.replaceState( { list:list.id }, document.title, _mtt.urlForList(list)) } diff --git a/src/includes/mytinytodo_ajax_storage.js b/src/includes/mytinytodo_ajax_storage.js index 9d767c9..825c74d 100644 --- a/src/includes/mytinytodo_ajax_storage.js +++ b/src/includes/mytinytodo_ajax_storage.js @@ -7,19 +7,19 @@ // AJAX myTinyTodo Storage (function(){ - + "use strict"; var mtt; -function mytinytodoStorageAjax(amtt) +function mytinytodoStorageAjax(amtt) { this.mtt = mtt = amtt; } window.mytinytodoStorageAjax = mytinytodoStorageAjax; -mytinytodoStorageAjax.prototype = +mytinytodoStorageAjax.prototype = { /* required method */ request:function(action, params, callback) @@ -61,7 +61,7 @@ mytinytodoStorageAjax.prototype = $.post(this.mtt.mttUrl+'ajax.php?newTask', { list:params.list, title: params.title, tag:params.tag }, callback, 'json'); }, - + fullNewTask: function(params, callback) { @@ -102,7 +102,7 @@ mytinytodoStorageAjax.prototype = $.getJSON(this.mtt.mttUrl+'ajax.php?setPrio='+params.id+'&prio='+params.prio+'&rnd='+Math.random(), callback); }, - + setSort: function(params, callback) { $.post(this.mtt.mttUrl+'ajax.php?setSort', { list:params.list, sort:params.sort }, callback, 'json'); @@ -116,7 +116,7 @@ mytinytodoStorageAjax.prototype = } $.post(this.mtt.mttUrl+'ajax.php?changeOrder', { order:order }, callback, 'json'); }, - + suggestTags: function(params, callback) { $.getJSON(this.mtt.mttUrl+'ajax.php?suggestTags', {list:params.list, q:params.q, rnd:Math.random()}, callback); @@ -136,12 +136,12 @@ mytinytodoStorageAjax.prototype = { $.post(this.mtt.mttUrl+'ajax.php?parseTaskStr', { list:params.list, title:params.title, tag:params.tag }, callback, 'json'); }, - + // Lists addList: function(params, callback) { - $.post(this.mtt.mttUrl+'ajax.php?addList', { name:params.name }, callback, 'json'); + $.post(this.mtt.mttUrl+'ajax.php?addList', { name:params.name }, callback, 'json'); }, @@ -159,12 +159,12 @@ mytinytodoStorageAjax.prototype = { $.post(this.mtt.mttUrl+'ajax.php?publishList', { list:params.list, publish:params.publish }, callback, 'json'); }, - + setShowNotesInList: function(params, callback) { $.post(this.mtt.mttUrl+'ajax.php?setShowNotesInList', { list:params.list, shownotes:params.shownotes }, callback, 'json'); }, - + setHideList: function(params, callback) { $.post(this.mtt.mttUrl+'ajax.php?setHideList', { list:params.list, hide:params.hide }, callback, 'json'); diff --git a/src/mytinytodo_lang.php b/src/mytinytodo_lang.php index 3908bbb..b32c2df 100644 --- a/src/mytinytodo_lang.php +++ b/src/mytinytodo_lang.php @@ -118,7 +118,7 @@ class DefaultLang 'list_select' => "Select list", 'list_export' => "Export", 'list_export_csv' => "CSV", - 'list_export_ical' => "iCalendar", + 'list_export_ical' => "iCalendar", 'list_rssfeed' => "RSS Feed", 'alltags' => "All tags:", 'alltags_show' => "Show all", @@ -219,29 +219,29 @@ class DefaultLang $c = 'Lang'; self::$instance = new $c; } - return self::$instance; + return self::$instance; } - + public function json($langFile = '', $pretty = 0) { $a = array(); - + if ($langFile != '') { $ah = $this->loadLangHeader($langFile); $a['_header'] = $ah; } - + if ($this->rtl()) { $a['_rtl'] = $this->rtl(); } - + foreach ( $this->default_inc as $k=>$v ) { if ( isset($this->inc[$k]) ) { $v = $this->inc[$k]; } $a[$k] = $v; } - + foreach ( $this->default_js as $k=>$v ) { if ( isset($this->js[$k]) ) { $v = $this->js[$k]; @@ -249,14 +249,14 @@ class DefaultLang $v = str_replace("\\n", "\n", $v); $a[$k] = $v; } - + $encOptions = JSON_UNESCAPED_UNICODE;; if ($pretty) { $encOptions |= JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES; } return json_encode($a, $encOptions); } - + function loadLangHeader($langFile) { if (!file_exists($langFile)) { @@ -265,7 +265,7 @@ class DefaultLang $contents = file_get_contents($langFile); $a = array(); - + # parse head comment if(preg_match("|/\\*\s*myTinyTodo language pack([\s\S]+?)\\*/|", $contents, $m)) { @@ -296,6 +296,6 @@ class DefaultLang } } - return $a; + return $a; } } diff --git a/src/settings.php b/src/settings.php index 460e511..be4e19a 100644 --- a/src/settings.php +++ b/src/settings.php @@ -22,14 +22,14 @@ if(isset($_POST['save'])) $langs = getLangs(); Config::$params['lang']['options'] = array_keys($langs); Config::set('lang', _post('lang')); - + // in Demo mode we can set only language by cookies if(defined('MTTDEMO')) { setcookie('lang', Config::get('lang'), 0, url_dir(Config::get('url')=='' ? getRequestUri() : Config::getUrl('url'))); $t['saved'] = 1; jsonExit($t); } - + if(isset($_POST['password']) && $_POST['password'] != '') Config::set('password', $_POST['password']); elseif(!_post('allowpassword')) Config::set('password', ''); Config::set('smartsyntax', (int)_post('smartsyntax')); @@ -191,12 +191,12 @@ header('Content-type:text/html; charset=utf-8'); : - - + +

    Notice! You can use old language files after downloading in the new format and copying to the /content/lang/ folder.
    - + Download json file - "); - } - - # update process - if($ver == '1.3.1') - { - update_131_14($db, $dbtype); - } - if($ver == '1.3.0') - { - update_130_131($db, $dbtype); - update_131_14($db, $dbtype); - } - if($ver == '1.2') - { - update_12_13($db, $dbtype); - update_130_131($db, $dbtype); - update_131_14($db, $dbtype); - } - elseif($ver == '1.1') - { - update_11_12($db, $dbtype); - update_12_13($db, $dbtype); - update_130_131($db, $dbtype); - update_131_14($db, $dbtype); - } -} -echo "Done

    Attention! Delete this file for security reasons."; -printFooter(); - - -function get_ver($db, $dbtype) -{ - if(!$db || $dbtype == '') return ''; - if(!$db->table_exists($db->prefix.'todolist')) return ''; - $v = '1.0'; - if(!$db->table_exists($db->prefix.'tags')) return $v; - $v = '1.1'; - if($dbtype == 'mysql') { - if(!has_field_mysql($db, $db->prefix.'todolist', 'duedate')) return $v; - } else { - if(!has_field_sqlite($db, $db->prefix.'todolist', 'duedate')) return $v; - } - $v = '1.2'; - if(!$db->table_exists($db->prefix.'lists')) return $v; - $v = '1.3.0'; - if($dbtype == 'mysql') { - if(!has_field_mysql($db, $db->prefix.'todolist', 'd_completed')) return $v; - } else { - if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_completed')) return $v; - } - $v = '1.3.1'; - if($dbtype == 'mysql') { - if(!has_field_mysql($db, $db->prefix.'todolist', 'd_edited')) return $v; - } else { - if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_edited')) return $v; - } - $v = '1.4'; - return $v; -} - -function exitMessage($s) -{ - echo $s; - printFooter(); - exit; -} - -function printFooter() -{ - echo ""; -} - - -function has_field_sqlite($db, $table, $field) -{ - $q = $db->dq("PRAGMA table_info(". $db->quote($table). ")"); - while($r = $q->fetch_row()) { - if($r[1] == $field) return true; - } - return false; -} - -function has_field_mysql($db, $table, $field) -{ - $q = $db->dq("DESCRIBE `$table`"); - while($r = $q->fetch_row()) { - if($r[0] == $field) return true; - } - return false; -} - -function testConnect(&$error) -{ - try - { - if(Config::get('db') == 'mysql') - { - require_once(MTTINC. 'class.db.mysql.php'); - $db = new Database_Mysql; - $db->connect(Config::get('mysql.host'), Config::get('mysql.user'), Config::get('mysql.password'), Config::get('mysql.db')); - } else - { - if(false === $f = @fopen(MTTPATH. 'db/todolist.db', 'a+')) throw new Exception("database file is not readable/writable"); - else fclose($f); - - if(!is_writable(MTTPATH. 'db/')) throw new Exception("database directory ('db') is not writable"); - - require_once(MTTINC. 'class.db.sqlite3.php'); - $db = new Database_Sqlite3; - $db->connect(MTTPATH. 'db/todolist.db'); - } - } catch(Exception $e) { - $error = $e->getMessage(); - return 0; - } - return 1; -} - -function myExceptionHandler($e) -{ - echo '
    Fatal Error: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine() . ''. - "\n
    ". $e->getTraceAsString() . "
    \n"; - exit; -} - - -### 1.1-1.2 ########## -function update_11_12($db, $dbtype) -{ - if($dbtype == 'mysql') $db->ex("ALTER TABLE todolist ADD `duedate` DATE default NULL"); - else $db->ex("ALTER TABLE todolist ADD duedate DATE default NULL"); - - # Fixing broken tags - $db->ex("BEGIN"); - $db->ex("DELETE FROM tags"); - $db->ex("DELETE FROM tag2task"); - $q = $db->dq("SELECT id,tags FROM todolist"); - while($r = $q->fetch_assoc()) - { - if($r['tags'] == '') continue; - $tag_ids = prepare_tags($r['tags']); - if($tag_ids) update_task_tags($r['id'], $tag_ids); - } - $db->ex("COMMIT"); -} - -function prepare_tags(&$tags_str) -{ - $tag_ids = array(); - $tag_names = array(); - $tags = explode(',', $tags_str); - foreach($tags as $v) - { - # remove duplicate tags? - $tag = str_replace(array('"',"'"),array('',''),trim($v)); - if($tag == '') continue; - list($tag_id,$tag_name) = get_or_create_tag($tag); - if($tag_id && !in_array($tag_id, $tag_ids)) { - $tag_ids[] = $tag_id; - $tag_names[] = $tag_name; - } - } - $tags_str = implode(',', $tag_names); - return $tag_ids; -} - -function get_or_create_tag($name) -{ - global $db; - $tag = $db->sq("SELECT id,name FROM tags WHERE name=?", $name); - if($tag) return $tag; - - # need to create tag - $db->ex("INSERT INTO tags (name) VALUES (?)", $name); - return array($db->last_insert_id(), $name); -} - -function update_task_tags($id, $tag_ids) -{ - global $db; - foreach($tag_ids as $v) { - $db->ex("INSERT INTO tag2task (task_id,tag_id) VALUES ($id,$v)"); - } - $db->ex("UPDATE tags SET tags_count=tags_count+1 WHERE id IN (". implode(',', $tag_ids). ")"); -} - -### end 1.1-1.2 ##### - -### 1.2-1.3 ########## -function update_12_13($db, $dbtype) -{ - # update config - Config::save(); - - # and then db - $db->ex("BEGIN"); - if($dbtype=='mysql') - { - $db->ex( -"CREATE TABLE lists ( - `id` INT UNSIGNED NOT NULL auto_increment, - `name` VARCHAR(50) NOT NULL default '', - PRIMARY KEY(`id`) -) CHARSET=utf8 "); - $db->ex("ALTER TABLE todolist ADD `list_id` INT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE tags ADD `list_id` INT UNSIGNED NOT NULL default 0"); - - $db->ex("ALTER TABLE todolist ADD KEY(`list_id`)"); - $db->ex("DROP INDEX `name` ON tags"); - $db->ex("ALTER TABLE tags ADD UNIQUE KEY `listid_name` (`list_id`,`name`)"); - } - else - { - $db->ex( -"CREATE TABLE lists ( - id INTEGER PRIMARY KEY, - name VARCHAR(50) NOT NULL -) "); - $db->ex("ALTER TABLE todolist ADD list_id INTEGER UNSIGNED NOT NULL default 0"); - $db->ex("CREATE INDEX todolist_list_id ON todolist (list_id)"); - - $db->ex( -"CREATE TEMPORARY TABLE tags_backup ( - id INTEGER, - name VARCHAR(50) NOT NULL, - tags_count INT default 0 -) "); - $db->ex("INSERT INTO tags_backup SELECT id,name,tags_count FROM tags"); - $db->ex("DROP TABLE tags"); - $db->ex( -"CREATE TABLE tags ( - id INTEGER PRIMARY KEY, - name VARCHAR(50) NOT NULL, - tags_count INT default 0, - list_id INTEGER UNSIGNED NOT NULL default 0 -) "); - $db->ex("INSERT INTO tags (id,name,tags_count) SELECT id,name,tags_count FROM tags_backup"); - $db->ex("CREATE UNIQUE INDEX tags_listid_name ON tags (list_id,name COLLATE NOCASE) "); - $db->ex("DROP TABLE tags_backup"); - } - $db->ex("COMMIT"); - - $db->ex("INSERT INTO lists (name,d_created) VALUES (?,?)", array('Todo', time())); - $db->ex("UPDATE todolist SET list_id=1"); - -} - -### end 1.2-1.3 ##### - - -### 1.3.0 to 1.3.1 ########## -function update_130_131($db, $dbtype) -{ - $tz = null; - if(isset($_POST['tz'])) { - $tz = (int)$_POST['tz']; - if($tz<-720 || $tz>720 || $tz%30!=0) $tz = null; - else $tz = $tz*60; - } - if(is_null($tz)) $tz = (int)date('Z'); - -# if($dbtype=='sqlite') { -# $temp_store_pragma = $db->sq("PRAGMA temp_store"); -# $db->ex("PRAGMA temp_store = MEMORY"); -# } - - $db->ex("BEGIN"); - if($dbtype=='mysql') - { - $db->ex("ALTER TABLE lists ADD `ow` INT NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD `d_created` INT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD `sorting` TINYINT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD `published` TINYINT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD `taskview` INT UNSIGNED NOT NULL default 0"); - - $db->ex("ALTER TABLE todolist ADD `d_created` INT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE todolist ADD `d_completed` INT UNSIGNED NOT NULL default 0"); - - # convert task date... - $db_session_timezone = $db->sq("SELECT @@session.time_zone");; - $db->ex("SET time_zone='+0:00'"); - $tz = -1*$tz; - $db->ex("UPDATE todolist SET d_created = UNIX_TIMESTAMP(d) + TIME_TO_SEC(TIMEDIFF(NOW(),UTC_TIMESTAMP())) ".($tz<0?'-':'+').abs($tz)); - $db->ex("SET time_zone=?", array($db_session_timezone)); - - $db->ex("ALTER TABLE todolist DROP `d`"); - } - else - { - $db->ex("ALTER TABLE lists ADD ow INTEGER NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD d_created INTEGER UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD sorting TINYINT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD published TINYINT UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE lists ADD taskview INTEGER UNSIGNED NOT NULL default 0"); - - $db->ex("ALTER TABLE todolist ADD d_created INTEGER UNSIGNED NOT NULL default 0"); - $db->ex("ALTER TABLE todolist ADD d_completed INTEGER UNSIGNED NOT NULL default 0"); - - # convert task date to timestamp - $tz = -1*$tz; - $db->ex("UPDATE todolist SET d_created=strftime('%s',d) ".($tz<0?'-':'+').abs($tz)); - - # drop unnecessary field 'd' - $db->ex( -"CREATE TEMPORARY TABLE todolist_backup ( - id INTEGER, - list_id INTEGER UNSIGNED NOT NULL default 0, - d_created INTEGER UNSIGNED NOT NULL default 0, - d_completed INTEGER UNSIGNED NOT NULL default 0, - compl TINYINT UNSIGNED NOT NULL default 0, - title VARCHAR(250) NOT NULL, - note TEXT, - prio TINYINT NOT NULL default 0, - ow INT NOT NULL default 0, - tags VARCHAR(250) NOT NULL default '', - duedate DATE default NULL -) "); - $db->ex("INSERT INTO todolist_backup (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate) ". - " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM todolist"); - $db->ex("DROP TABLE todolist"); - - $db->ex( -"CREATE TABLE todolist ( - id INTEGER PRIMARY KEY, - list_id INTEGER UNSIGNED NOT NULL default 0, - d_created INTEGER UNSIGNED NOT NULL default 0, - d_completed INTEGER UNSIGNED NOT NULL default 0, - compl TINYINT UNSIGNED NOT NULL default 0, - title VARCHAR(250) NOT NULL, - note TEXT, - prio TINYINT NOT NULL default 0, - ow INT NOT NULL default 0, - tags VARCHAR(250) NOT NULL default '', - duedate DATE default NULL -) "); - $db->ex("CREATE INDEX list_id ON todolist (list_id)"); - - $db->ex("INSERT INTO todolist (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate) ". - " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM todolist_backup"); - $db->ex("DROP TABLE todolist_backup"); - } - - $sort = 0; - if(isset($_COOKIE['sort']) && $_COOKIE['sort'] != ''){ - $sort = (int)$_COOKIE['sort']; - if($sort < 0 || $sort > 2) $sort = 0; - } - - if(Config::get('password') != '' && Config::get('allowread')) $published = 1; - else $published = 0; - - $db->ex("UPDATE lists SET d_created=?, sorting=?, published=?", array(time(), $sort, $published)); - $db->ex("UPDATE todolist SET d_completed=d_created WHERE compl=1"); - - $db->ex("COMMIT"); - -# if($dbtype=='sqlite') { -# $db->ex("PRAGMA temp_store = $temp_store_pragma"); -# } -} - -### end of 1.3.0 to 1.3.1 ########## - -### update v1.3.1 to v1.4 ########## -function update_131_14($db, $dbtype) -{ - $db->ex("BEGIN"); - if($dbtype=='mysql') - { - $db->ex("DROP TABLE {$db->prefix}tags"); - $db->ex( - "CREATE TABLE {$db->prefix}tags ( - `id` INT UNSIGNED NOT NULL auto_increment, - `name` VARCHAR(50) NOT NULL, - PRIMARY KEY(`id`), - UNIQUE KEY `name` (`name`) - ) CHARSET=utf8 "); - - $db->ex("ALTER TABLE {$db->prefix}todolist CHANGE `tags` `tags` VARCHAR(600) NOT NULL default ''"); - $db->ex("ALTER TABLE {$db->prefix}todolist ADD `tags_ids` VARCHAR(250) NOT NULL default ''"); - $db->ex("ALTER TABLE {$db->prefix}todolist ADD `uuid` CHAR(36) NOT NULL default ''"); - $db->ex("ALTER TABLE {$db->prefix}todolist ADD `d_edited` INT UNSIGNED NOT NULL default 0"); - - $db->ex("ALTER TABLE {$db->prefix}tag2task ADD `list_id` INT UNSIGNED NOT NULL"); - $db->ex("ALTER TABLE {$db->prefix}tag2task ADD KEY(`list_id`)"); - - $db->ex("ALTER TABLE {$db->prefix}lists ADD `uuid` CHAR(36) NOT NULL default ''"); - $db->ex("ALTER TABLE {$db->prefix}lists ADD `d_edited` INT UNSIGNED NOT NULL default 0"); - - } - else #sqlite - { - # changes in tags table: fully new - $db->ex("DROP TABLE {$db->prefix}tags"); //index will be deleted too - $db->ex( - "CREATE TABLE {$db->prefix}tags ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name VARCHAR(50) NOT NULL COLLATE NOCASE - ) "); - $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); - - # changes in todolist table: uuid, d_edited, tags, tags_ids - $db->ex( - "CREATE TABLE todolist_new ( - id INTEGER PRIMARY KEY, - uuid CHAR(36) NOT NULL default '', - list_id INTEGER UNSIGNED NOT NULL default 0, - d_created INTEGER UNSIGNED NOT NULL default 0, - d_completed INTEGER UNSIGNED NOT NULL default 0, - d_edited INTEGER UNSIGNED NOT NULL default 0, - compl TINYINT UNSIGNED NOT NULL default 0, - title VARCHAR(250) NOT NULL, - note TEXT, - prio TINYINT NOT NULL default 0, - ow INTEGER NOT NULL default 0, - tags VARCHAR(600) NOT NULL default '', - tags_ids VARCHAR(250) NOT NULL default '', - duedate DATE default NULL - ) "); - $db->ex("INSERT INTO todolist_new (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate)". - " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM {$db->prefix}todolist"); - $db->ex("DROP TABLE {$db->prefix}todolist"); - $db->ex("ALTER TABLE todolist_new RENAME TO {$db->prefix}todolist"); - $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); #1st index of 2 - - # changes in tag2task table: new column and index, new names of indexes - $db->ex("ALTER TABLE {$db->prefix}tag2task ADD list_id INTEGER NOT NULL default 0"); - $db->ex("DROP INDEX tag_id"); - $db->ex("DROP INDEX task_id "); - $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); - $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); - $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); - - # changes in lists table: uuid, d_edited - $db->ex("ALTER TABLE {$db->prefix}lists ADD uuid CHAR(36) NOT NULL default ''"); - $db->ex("ALTER TABLE {$db->prefix}lists ADD d_edited INTEGER UNSIGNED NOT NULL default 0"); - - } - - # recreate tags - $db->ex("DELETE FROM {$db->prefix}tag2task"); - - $q = $db->dq("SELECT id,list_id,tags FROM {$db->prefix}todolist WHERE tags != ''"); - $ar = array(); - while($r = $q->fetch_assoc()) $ar[] = $r; - foreach($ar as $r) - { - $aTags = v14_prepareTags($r['tags']); - if($aTags) - { - v14_addTaskTags($r['id'], $aTags['ids'], $r['list_id']); - $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=".$r['id'], - array(implode(',',$aTags['tags']), implode(',',$aTags['ids'])) ); - } - } - - # fix bug with empty lists.d_created - $db->ex("UPDATE {$db->prefix}lists SET d_created=?", time()); - - # init d_edited - $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_created"); - $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_completed WHERE d_completed > d_edited"); - $db->ex("UPDATE {$db->prefix}lists SET d_edited=d_created"); - - # add UUID - $q = $db->dq("SELECT id FROM {$db->prefix}todolist"); - $ar = array(); - while($r = $q->fetch_assoc()) $ar[] = $r; - foreach($ar as $r) { - $db->ex("UPDATE {$db->prefix}todolist SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); - } - - $q = $db->dq("SELECT id FROM {$db->prefix}lists"); - $ar = array(); - while($r = $q->fetch_assoc()) $ar[] = $r; - foreach($ar as $r) { - $db->ex("UPDATE {$db->prefix}lists SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); - } - - # create unique indexes for UUID - if($dbtype=='mysql') - { - $db->ex("ALTER TABLE {$db->prefix}lists ADD UNIQUE KEY (`uuid`)"); - $db->ex("ALTER TABLE {$db->prefix}todolist ADD UNIQUE KEY (`uuid`)"); - } - else - { - $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); - $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); - } - - $db->ex("COMMIT"); -} - -function v14_prepareTags($tagsStr) -{ - $tags = explode(',', $tagsStr); - if(!$tags) return 0; - - $aTags = array('tags'=>array(), 'ids'=>array()); - foreach($tags as $tag) - { - $tag = str_replace(array('"',"'",'<','>','&','/','\\','^'),'',trim($tag)); - if($tag == '') continue; - - $aTag = v14_getOrCreateTag($tag); - if($aTag && !in_array($aTag['id'], $aTags['ids'])) { - $aTags['tags'][] = $aTag['name']; - $aTags['ids'][] = $aTag['id']; - } - } - return $aTags; -} - -function v14_getOrCreateTag($name) -{ - global $db; - $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); - if($tagId) return array('id'=>$tagId, 'name'=>$name); - - $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); - return array('id'=>$db->last_insert_id(), 'name'=>$name); -} - -function v14_addTaskTags($taskId, $tagIds, $listId) -{ - global $db; - if(!$tagIds) return; - foreach($tagIds as $tagId) - { - $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); - } -} -### end of 1.4 ##### - - + + Licensed under the GNU GPL v2 license. See file COPYRIGHT for details. +*/ + +set_exception_handler('myExceptionHandler'); + +# Check old config file (prior v1.3) +require_once('./db/config.php'); +if(!isset($config['db'])) +{ + if(isset($config['mysql'])) { + $config['db'] = 'mysql'; + $config['mysql.host'] = $config['mysql'][0]; + $config['mysql.db'] = $config['mysql'][3]; + $config['mysql.user'] = $config['mysql'][1]; + $config['mysql.password'] = $config['mysql'][2]; + } else { + $config['db'] = 'sqlite'; + } + if(isset($config['allow']) && $config['allow'] == 'read') $config['allowread'] = 1; +} + +if($config['db'] != '') +{ + require_once('./init.php'); + if ( !is_logged() ) + { + die("Access denied!
    Disable password protection or Log in."); + } + $dbtype = (strtolower(get_class($db)) == 'database_mysql') ? 'mysql' : 'sqlite'; +} +else +{ + if(!defined('MTTPATH')) define('MTTPATH', dirname(__FILE__) .'/'); + if(!defined('MTTINC')) define('MTTINC', MTTPATH. 'includes/'); + require_once(MTTINC. 'common.php'); + Config::loadConfig($config); + unset($config); + + $db = 0; + $dbtype = ''; +} + +$lastVer = '1.4'; +echo 'myTinyTodo @VERSION Setup'; +echo "myTinyTodo @VERSION Setup

    "; + +# determine current installed version +$ver = get_ver($db, $dbtype); + +if(!$ver) +{ + # Which DB to select + if(!isset($_POST['installdb']) && !isset($_POST['install'])) + { + exitMessage("
    Select database type to use:

    +

    +
    +
    "); + } + elseif(isset($_POST['installdb'])) + { + # Save configuration + $dbtype = ($_POST['installdb'] == 'mysql') ? 'mysql' : 'sqlite'; + Config::set('db', $dbtype); + if($dbtype == 'mysql') { + Config::set('mysql.host', _post('mysql_host')); + Config::set('mysql.db', _post('mysql_db')); + Config::set('mysql.user', _post('mysql_user')); + Config::set('mysql.password', _post('mysql_password')); + Config::set('prefix', trim(_post('prefix'))); + } + if(!testConnect($error)) { + exitMessage("Database connection error: $error"); + } + if(!is_writable('./db/config.php')) { + exitMessage("Config file ('db/config.php') is not writable."); + } + Config::save(); + exitMessage("This will create myTinyTodo database
    "); + } + + # install database + if($dbtype == 'mysql') + { + try + { + + $db->ex( +"CREATE TABLE {$db->prefix}lists ( + `id` INT UNSIGNED NOT NULL auto_increment, + `uuid` CHAR(36) NOT NULL default '', + `ow` INT NOT NULL default 0, + `name` VARCHAR(50) NOT NULL default '', + `d_created` INT UNSIGNED NOT NULL default 0, + `d_edited` INT UNSIGNED NOT NULL default 0, + `sorting` TINYINT UNSIGNED NOT NULL default 0, + `published` TINYINT UNSIGNED NOT NULL default 0, + `taskview` INT UNSIGNED NOT NULL default 0, + PRIMARY KEY(`id`), + UNIQUE KEY(`uuid`) +) CHARSET=utf8 "); + + + $db->ex( +"CREATE TABLE {$db->prefix}todolist ( + `id` INT UNSIGNED NOT NULL auto_increment, + `uuid` CHAR(36) NOT NULL default '', + `list_id` INT UNSIGNED NOT NULL default 0, + `d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `d_edited` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `compl` TINYINT UNSIGNED NOT NULL default 0, + `title` VARCHAR(250) NOT NULL, + `note` TEXT, + `prio` TINYINT NOT NULL default 0, /* priority -,0,+ */ + `ow` INT NOT NULL default 0, /* order weight */ + `tags` VARCHAR(600) NOT NULL default '', /* for fast access to task tags */ + `tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */ + `duedate` DATE default NULL, + PRIMARY KEY(`id`), + KEY(`list_id`), + UNIQUE KEY(`uuid`) +) CHARSET=utf8 "); + + + $db->ex( +"CREATE TABLE {$db->prefix}tags ( + `id` INT UNSIGNED NOT NULL auto_increment, + `name` VARCHAR(50) NOT NULL, + PRIMARY KEY(`id`), + UNIQUE KEY `name` (`name`) +) CHARSET=utf8 "); + + + $db->ex( +"CREATE TABLE {$db->prefix}tag2task ( + `tag_id` INT UNSIGNED NOT NULL, + `task_id` INT UNSIGNED NOT NULL, + `list_id` INT UNSIGNED NOT NULL, + KEY(`tag_id`), + KEY(`task_id`), + KEY(`list_id`) /* for tagcloud */ +) CHARSET=utf8 "); + + + } catch (Exception $e) { + exitMessage("Error: ". htmlarray($e->getMessage())); + } + } + else #sqlite + { + try + { + + $db->ex( +"CREATE TABLE {$db->prefix}lists ( + id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL, + ow INTEGER NOT NULL default 0, + name VARCHAR(50) NOT NULL, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, + sorting TINYINT UNSIGNED NOT NULL default 0, + published TINYINT UNSIGNED NOT NULL default 0, + taskview INTEGER UNSIGNED NOT NULL default 0 +) "); + + $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); + + $db->ex( +"CREATE TABLE {$db->prefix}todolist ( + id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL, + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INTEGER NOT NULL default 0, + tags VARCHAR(600) NOT NULL default '', + tags_ids VARCHAR(250) NOT NULL default '', + duedate DATE default NULL +) "); + $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); + $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); + + + $db->ex( +"CREATE TABLE {$db->prefix}tags ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(50) NOT NULL COLLATE NOCASE +) "); + $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); + + + $db->ex( +"CREATE TABLE {$db->prefix}tag2task ( + tag_id INTEGER NOT NULL, + task_id INTEGER NOT NULL, + list_id INTEGER NOT NULL +) "); + $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); + $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); + $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); /* for tagcloud */ + + } catch (Exception $e) { + exitMessage("Error: ". htmlarray($e->getMessage())); + } + } + + # create default list + $db->ex( "INSERT INTO {$db->prefix}lists (uuid,name,d_created,taskview) VALUES (?,?,?,?)", array(generateUUID(), 'Todo', time(), 1) ); + +} +elseif($ver == $lastVer) +{ + exitMessage("Installed version does not require database update."); +} +else +{ + if(!in_array($ver, array('1.1','1.2','1.3.0','1.3.1'))) { + exitMessage("Can not update. Unsupported database version ($ver)."); + } + if(!isset($_POST['update'])) { + exitMessage("Update database v$ver +
    + + "); + } + + # update process + if($ver == '1.3.1') + { + update_131_14($db, $dbtype); + } + if($ver == '1.3.0') + { + update_130_131($db, $dbtype); + update_131_14($db, $dbtype); + } + if($ver == '1.2') + { + update_12_13($db, $dbtype); + update_130_131($db, $dbtype); + update_131_14($db, $dbtype); + } + elseif($ver == '1.1') + { + update_11_12($db, $dbtype); + update_12_13($db, $dbtype); + update_130_131($db, $dbtype); + update_131_14($db, $dbtype); + } +} +echo "Done

    Attention! Delete this file for security reasons."; +printFooter(); + + +function get_ver($db, $dbtype) +{ + if(!$db || $dbtype == '') return ''; + if(!$db->table_exists($db->prefix.'todolist')) return ''; + $v = '1.0'; + if(!$db->table_exists($db->prefix.'tags')) return $v; + $v = '1.1'; + if($dbtype == 'mysql') { + if(!has_field_mysql($db, $db->prefix.'todolist', 'duedate')) return $v; + } else { + if(!has_field_sqlite($db, $db->prefix.'todolist', 'duedate')) return $v; + } + $v = '1.2'; + if(!$db->table_exists($db->prefix.'lists')) return $v; + $v = '1.3.0'; + if($dbtype == 'mysql') { + if(!has_field_mysql($db, $db->prefix.'todolist', 'd_completed')) return $v; + } else { + if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_completed')) return $v; + } + $v = '1.3.1'; + if($dbtype == 'mysql') { + if(!has_field_mysql($db, $db->prefix.'todolist', 'd_edited')) return $v; + } else { + if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_edited')) return $v; + } + $v = '1.4'; + return $v; +} + +function exitMessage($s) +{ + echo $s; + printFooter(); + exit; +} + +function printFooter() +{ + echo ""; +} + + +function has_field_sqlite($db, $table, $field) +{ + $q = $db->dq("PRAGMA table_info(". $db->quote($table). ")"); + while($r = $q->fetch_row()) { + if($r[1] == $field) return true; + } + return false; +} + +function has_field_mysql($db, $table, $field) +{ + $q = $db->dq("DESCRIBE `$table`"); + while($r = $q->fetch_row()) { + if($r[0] == $field) return true; + } + return false; +} + +function testConnect(&$error) +{ + try + { + if(Config::get('db') == 'mysql') + { + require_once(MTTINC. 'class.db.mysql.php'); + $db = new Database_Mysql; + $db->connect(Config::get('mysql.host'), Config::get('mysql.user'), Config::get('mysql.password'), Config::get('mysql.db')); + } else + { + if(false === $f = @fopen(MTTPATH. 'db/todolist.db', 'a+')) throw new Exception("database file is not readable/writable"); + else fclose($f); + + if(!is_writable(MTTPATH. 'db/')) throw new Exception("database directory ('db') is not writable"); + + require_once(MTTINC. 'class.db.sqlite3.php'); + $db = new Database_Sqlite3; + $db->connect(MTTPATH. 'db/todolist.db'); + } + } catch(Exception $e) { + $error = $e->getMessage(); + return 0; + } + return 1; +} + +function myExceptionHandler($e) +{ + echo '
    Fatal Error: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine() . ''. + "\n
    ". $e->getTraceAsString() . "
    \n"; + exit; +} + + +### 1.1-1.2 ########## +function update_11_12($db, $dbtype) +{ + if($dbtype == 'mysql') $db->ex("ALTER TABLE todolist ADD `duedate` DATE default NULL"); + else $db->ex("ALTER TABLE todolist ADD duedate DATE default NULL"); + + # Fixing broken tags + $db->ex("BEGIN"); + $db->ex("DELETE FROM tags"); + $db->ex("DELETE FROM tag2task"); + $q = $db->dq("SELECT id,tags FROM todolist"); + while($r = $q->fetch_assoc()) + { + if($r['tags'] == '') continue; + $tag_ids = prepare_tags($r['tags']); + if($tag_ids) update_task_tags($r['id'], $tag_ids); + } + $db->ex("COMMIT"); +} + +function prepare_tags(&$tags_str) +{ + $tag_ids = array(); + $tag_names = array(); + $tags = explode(',', $tags_str); + foreach($tags as $v) + { + # remove duplicate tags? + $tag = str_replace(array('"',"'"),array('',''),trim($v)); + if($tag == '') continue; + list($tag_id,$tag_name) = get_or_create_tag($tag); + if($tag_id && !in_array($tag_id, $tag_ids)) { + $tag_ids[] = $tag_id; + $tag_names[] = $tag_name; + } + } + $tags_str = implode(',', $tag_names); + return $tag_ids; +} + +function get_or_create_tag($name) +{ + global $db; + $tag = $db->sq("SELECT id,name FROM tags WHERE name=?", $name); + if($tag) return $tag; + + # need to create tag + $db->ex("INSERT INTO tags (name) VALUES (?)", $name); + return array($db->last_insert_id(), $name); +} + +function update_task_tags($id, $tag_ids) +{ + global $db; + foreach($tag_ids as $v) { + $db->ex("INSERT INTO tag2task (task_id,tag_id) VALUES ($id,$v)"); + } + $db->ex("UPDATE tags SET tags_count=tags_count+1 WHERE id IN (". implode(',', $tag_ids). ")"); +} + +### end 1.1-1.2 ##### + +### 1.2-1.3 ########## +function update_12_13($db, $dbtype) +{ + # update config + Config::save(); + + # and then db + $db->ex("BEGIN"); + if($dbtype=='mysql') + { + $db->ex( +"CREATE TABLE lists ( + `id` INT UNSIGNED NOT NULL auto_increment, + `name` VARCHAR(50) NOT NULL default '', + PRIMARY KEY(`id`) +) CHARSET=utf8 "); + $db->ex("ALTER TABLE todolist ADD `list_id` INT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE tags ADD `list_id` INT UNSIGNED NOT NULL default 0"); + + $db->ex("ALTER TABLE todolist ADD KEY(`list_id`)"); + $db->ex("DROP INDEX `name` ON tags"); + $db->ex("ALTER TABLE tags ADD UNIQUE KEY `listid_name` (`list_id`,`name`)"); + } + else + { + $db->ex( +"CREATE TABLE lists ( + id INTEGER PRIMARY KEY, + name VARCHAR(50) NOT NULL +) "); + $db->ex("ALTER TABLE todolist ADD list_id INTEGER UNSIGNED NOT NULL default 0"); + $db->ex("CREATE INDEX todolist_list_id ON todolist (list_id)"); + + $db->ex( +"CREATE TEMPORARY TABLE tags_backup ( + id INTEGER, + name VARCHAR(50) NOT NULL, + tags_count INT default 0 +) "); + $db->ex("INSERT INTO tags_backup SELECT id,name,tags_count FROM tags"); + $db->ex("DROP TABLE tags"); + $db->ex( +"CREATE TABLE tags ( + id INTEGER PRIMARY KEY, + name VARCHAR(50) NOT NULL, + tags_count INT default 0, + list_id INTEGER UNSIGNED NOT NULL default 0 +) "); + $db->ex("INSERT INTO tags (id,name,tags_count) SELECT id,name,tags_count FROM tags_backup"); + $db->ex("CREATE UNIQUE INDEX tags_listid_name ON tags (list_id,name COLLATE NOCASE) "); + $db->ex("DROP TABLE tags_backup"); + } + $db->ex("COMMIT"); + + $db->ex("INSERT INTO lists (name,d_created) VALUES (?,?)", array('Todo', time())); + $db->ex("UPDATE todolist SET list_id=1"); + +} + +### end 1.2-1.3 ##### + + +### 1.3.0 to 1.3.1 ########## +function update_130_131($db, $dbtype) +{ + $tz = null; + if(isset($_POST['tz'])) { + $tz = (int)$_POST['tz']; + if($tz<-720 || $tz>720 || $tz%30!=0) $tz = null; + else $tz = $tz*60; + } + if(is_null($tz)) $tz = (int)date('Z'); + +# if($dbtype=='sqlite') { +# $temp_store_pragma = $db->sq("PRAGMA temp_store"); +# $db->ex("PRAGMA temp_store = MEMORY"); +# } + + $db->ex("BEGIN"); + if($dbtype=='mysql') + { + $db->ex("ALTER TABLE lists ADD `ow` INT NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD `d_created` INT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD `sorting` TINYINT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD `published` TINYINT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD `taskview` INT UNSIGNED NOT NULL default 0"); + + $db->ex("ALTER TABLE todolist ADD `d_created` INT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE todolist ADD `d_completed` INT UNSIGNED NOT NULL default 0"); + + # convert task date... + $db_session_timezone = $db->sq("SELECT @@session.time_zone");; + $db->ex("SET time_zone='+0:00'"); + $tz = -1*$tz; + $db->ex("UPDATE todolist SET d_created = UNIX_TIMESTAMP(d) + TIME_TO_SEC(TIMEDIFF(NOW(),UTC_TIMESTAMP())) ".($tz<0?'-':'+').abs($tz)); + $db->ex("SET time_zone=?", array($db_session_timezone)); + + $db->ex("ALTER TABLE todolist DROP `d`"); + } + else + { + $db->ex("ALTER TABLE lists ADD ow INTEGER NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD d_created INTEGER UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD sorting TINYINT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD published TINYINT UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE lists ADD taskview INTEGER UNSIGNED NOT NULL default 0"); + + $db->ex("ALTER TABLE todolist ADD d_created INTEGER UNSIGNED NOT NULL default 0"); + $db->ex("ALTER TABLE todolist ADD d_completed INTEGER UNSIGNED NOT NULL default 0"); + + # convert task date to timestamp + $tz = -1*$tz; + $db->ex("UPDATE todolist SET d_created=strftime('%s',d) ".($tz<0?'-':'+').abs($tz)); + + # drop unnecessary field 'd' + $db->ex( +"CREATE TEMPORARY TABLE todolist_backup ( + id INTEGER, + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INT NOT NULL default 0, + tags VARCHAR(250) NOT NULL default '', + duedate DATE default NULL +) "); + $db->ex("INSERT INTO todolist_backup (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate) ". + " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM todolist"); + $db->ex("DROP TABLE todolist"); + + $db->ex( +"CREATE TABLE todolist ( + id INTEGER PRIMARY KEY, + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INT NOT NULL default 0, + tags VARCHAR(250) NOT NULL default '', + duedate DATE default NULL +) "); + $db->ex("CREATE INDEX list_id ON todolist (list_id)"); + + $db->ex("INSERT INTO todolist (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate) ". + " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM todolist_backup"); + $db->ex("DROP TABLE todolist_backup"); + } + + $sort = 0; + if(isset($_COOKIE['sort']) && $_COOKIE['sort'] != ''){ + $sort = (int)$_COOKIE['sort']; + if($sort < 0 || $sort > 2) $sort = 0; + } + + if(Config::get('password') != '' && Config::get('allowread')) $published = 1; + else $published = 0; + + $db->ex("UPDATE lists SET d_created=?, sorting=?, published=?", array(time(), $sort, $published)); + $db->ex("UPDATE todolist SET d_completed=d_created WHERE compl=1"); + + $db->ex("COMMIT"); + +# if($dbtype=='sqlite') { +# $db->ex("PRAGMA temp_store = $temp_store_pragma"); +# } +} + +### end of 1.3.0 to 1.3.1 ########## + +### update v1.3.1 to v1.4 ########## +function update_131_14($db, $dbtype) +{ + $db->ex("BEGIN"); + if($dbtype=='mysql') + { + $db->ex("DROP TABLE {$db->prefix}tags"); + $db->ex( + "CREATE TABLE {$db->prefix}tags ( + `id` INT UNSIGNED NOT NULL auto_increment, + `name` VARCHAR(50) NOT NULL, + PRIMARY KEY(`id`), + UNIQUE KEY `name` (`name`) + ) CHARSET=utf8 "); + + $db->ex("ALTER TABLE {$db->prefix}todolist CHANGE `tags` `tags` VARCHAR(600) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `tags_ids` VARCHAR(250) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `uuid` CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `d_edited` INT UNSIGNED NOT NULL default 0"); + + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD `list_id` INT UNSIGNED NOT NULL"); + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD KEY(`list_id`)"); + + $db->ex("ALTER TABLE {$db->prefix}lists ADD `uuid` CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}lists ADD `d_edited` INT UNSIGNED NOT NULL default 0"); + + } + else #sqlite + { + # changes in tags table: fully new + $db->ex("DROP TABLE {$db->prefix}tags"); //index will be deleted too + $db->ex( + "CREATE TABLE {$db->prefix}tags ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(50) NOT NULL COLLATE NOCASE + ) "); + $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); + + # changes in todolist table: uuid, d_edited, tags, tags_ids + $db->ex( + "CREATE TABLE todolist_new ( + id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL default '', + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INTEGER NOT NULL default 0, + tags VARCHAR(600) NOT NULL default '', + tags_ids VARCHAR(250) NOT NULL default '', + duedate DATE default NULL + ) "); + $db->ex("INSERT INTO todolist_new (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate)". + " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM {$db->prefix}todolist"); + $db->ex("DROP TABLE {$db->prefix}todolist"); + $db->ex("ALTER TABLE todolist_new RENAME TO {$db->prefix}todolist"); + $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); #1st index of 2 + + # changes in tag2task table: new column and index, new names of indexes + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD list_id INTEGER NOT NULL default 0"); + $db->ex("DROP INDEX tag_id"); + $db->ex("DROP INDEX task_id "); + $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); + $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); + $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); + + # changes in lists table: uuid, d_edited + $db->ex("ALTER TABLE {$db->prefix}lists ADD uuid CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}lists ADD d_edited INTEGER UNSIGNED NOT NULL default 0"); + + } + + # recreate tags + $db->ex("DELETE FROM {$db->prefix}tag2task"); + + $q = $db->dq("SELECT id,list_id,tags FROM {$db->prefix}todolist WHERE tags != ''"); + $ar = array(); + while($r = $q->fetch_assoc()) $ar[] = $r; + foreach($ar as $r) + { + $aTags = v14_prepareTags($r['tags']); + if($aTags) + { + v14_addTaskTags($r['id'], $aTags['ids'], $r['list_id']); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=".$r['id'], + array(implode(',',$aTags['tags']), implode(',',$aTags['ids'])) ); + } + } + + # fix bug with empty lists.d_created + $db->ex("UPDATE {$db->prefix}lists SET d_created=?", time()); + + # init d_edited + $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_created"); + $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_completed WHERE d_completed > d_edited"); + $db->ex("UPDATE {$db->prefix}lists SET d_edited=d_created"); + + # add UUID + $q = $db->dq("SELECT id FROM {$db->prefix}todolist"); + $ar = array(); + while($r = $q->fetch_assoc()) $ar[] = $r; + foreach($ar as $r) { + $db->ex("UPDATE {$db->prefix}todolist SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); + } + + $q = $db->dq("SELECT id FROM {$db->prefix}lists"); + $ar = array(); + while($r = $q->fetch_assoc()) $ar[] = $r; + foreach($ar as $r) { + $db->ex("UPDATE {$db->prefix}lists SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); + } + + # create unique indexes for UUID + if($dbtype=='mysql') + { + $db->ex("ALTER TABLE {$db->prefix}lists ADD UNIQUE KEY (`uuid`)"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD UNIQUE KEY (`uuid`)"); + } + else + { + $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); + $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); + } + + $db->ex("COMMIT"); +} + +function v14_prepareTags($tagsStr) +{ + $tags = explode(',', $tagsStr); + if(!$tags) return 0; + + $aTags = array('tags'=>array(), 'ids'=>array()); + foreach($tags as $tag) + { + $tag = str_replace(array('"',"'",'<','>','&','/','\\','^'),'',trim($tag)); + if($tag == '') continue; + + $aTag = v14_getOrCreateTag($tag); + if($aTag && !in_array($aTag['id'], $aTags['ids'])) { + $aTags['tags'][] = $aTag['name']; + $aTags['ids'][] = $aTag['id']; + } + } + return $aTags; +} + +function v14_getOrCreateTag($name) +{ + global $db; + $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); + if($tagId) return array('id'=>$tagId, 'name'=>$name); + + $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); + return array('id'=>$db->last_insert_id(), 'name'=>$name); +} + +function v14_addTaskTags($taskId, $tagIds, $listId) +{ + global $db; + if(!$tagIds) return; + foreach($tagIds as $tagId) + { + $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); + } +} +### end of 1.4 ##### + + ?> \ No newline at end of file diff --git a/src/tmp/.htaccess b/src/tmp/.htaccess index 3418e55..8d2f256 100644 --- a/src/tmp/.htaccess +++ b/src/tmp/.htaccess @@ -1 +1 @@ -deny from all \ No newline at end of file +deny from all