diff --git a/src/ajax.php b/src/ajax.php index d1555fa..552ca76 100644 --- a/src/ajax.php +++ b/src/ajax.php @@ -33,7 +33,7 @@ elseif(isset($_GET['loadTasks'])) stop_gpc($_GET); $listId = (int)_get('list'); check_read_access($listId); - $sqlWhere = ' AND todolist.list_id='. $listId; + $sqlWhere = " AND {$db->prefix}todolist.list_id=". $listId; if(_get('compl') == 0) $sqlWhere .= ' AND compl=0'; $inner = ''; @@ -113,7 +113,8 @@ elseif(isset($_GET['newTask'])) 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 (list_id,title,d_created,ow,prio) VALUES (?,?,?,?,?)", array($listId, $title, time(), $ow, $prio)); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio) VALUES (?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio) ); $id = $db->last_insert_id(); if($tags != '') { @@ -152,9 +153,9 @@ elseif(isset($_GET['fullNewTask'])) $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"); - if(is_null($duedate)) $duedate = 'NULL'; else $duedate = $db->quote($duedate); $db->ex("BEGIN"); - $db->dq("INSERT INTO {$db->prefix}todolist (list_id,title,d_created,ow,prio,note,duedate) VALUES($listId,?,?,$ow,$prio,?,$duedate)", array($title,time(),$note)); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio,note,duedate) VALUES(?,?,?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio, $note, $duedate) ); $id = $db->last_insert_id(); if($tags != '') { @@ -190,7 +191,8 @@ elseif(isset($_GET['completeTask'])) if($compl) $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=1"); else $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); $dateCompleted = $compl ? time() : 0; - $db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=? WHERE id=$id", array($dateCompleted)); + $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(); @@ -205,7 +207,7 @@ elseif(isset($_GET['editNote'])) $id = (int)_post('id'); stop_gpc($_POST); $note = str_replace("\r\n", "\n", trim(_post('note'))); - $db->dq("UPDATE {$db->prefix}todolist SET note=? WHERE id=$id", $note); + $db->dq("UPDATE {$db->prefix}todolist SET note=?,d_edited=? WHERE id=$id", array($note, time()) ); $t = array(); $t['total'] = 1; $t['list'][] = array('id'=>$id, 'note'=>nl2br(escapeTags($note)), 'noteText'=>(string)$note); @@ -241,9 +243,8 @@ elseif(isset($_GET['editTask'])) $tags_ids = implode(',',$aTags['ids']); addTaskTags($id, $aTags['ids'], $listId); } - if(is_null($duedate)) $duedate = 'NULL'; else $duedate = $db->quote($duedate); - $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,tags_ids=?,duedate=$duedate WHERE id=$id", - array($title,$note,$prio,$tags,$tags_ids) ); + $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,tags_ids=?,duedate=?,d_edited=? WHERE id=$id", + array($title, $note, $prio, $tags, $tags_ids, $duedate, time()) ); $db->ex("COMMIT"); $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); if($r) { @@ -271,7 +272,7 @@ elseif(isset($_GET['changeOrder'])) foreach($ad as $diff=>$ids) { if($diff >=0) $set = "ow=ow+".$diff; else $set = "ow=ow-".abs($diff); - $db->dq("UPDATE {$db->prefix}todolist SET $set WHERE id IN (".implode(',',$ids).")"); + $db->dq("UPDATE {$db->prefix}todolist SET $set,d_edited=? WHERE id IN (".implode(',',$ids).")", array(time()) ); } $db->ex("COMMIT"); $t['total'] = 1; @@ -327,7 +328,7 @@ elseif(isset($_GET['setPrio'])) $prio = (int)_get('prio'); if($prio < -1) $prio = -1; elseif($prio > 2) $prio = 2; - $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio WHERE id=$id"); + $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio,d_edited=? WHERE id=$id", array(time()) ); $t = array(); $t['total'] = 1; $t['list'][] = array('id'=>$id, 'prio'=>$prio); @@ -377,7 +378,8 @@ elseif(isset($_GET['addList'])) $t['total'] = 0; $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}lists"); - $db->dq("INSERT INTO {$db->prefix}lists (name,ow) VALUES (?,?)", array($name,$ow)); + $db->dq("INSERT INTO {$db->prefix}lists (uuid,name,ow,d_created,d_edited) VALUES (?,?,?,?,?)", + array(generateUUID(), $name, $ow, time(), time()) ); $id = $db->last_insert_id(); $t['total'] = 1; $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); @@ -393,7 +395,7 @@ elseif(isset($_GET['renameList'])) $t['total'] = 0; $id = (int)_post('list'); $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); - $db->dq("UPDATE {$db->prefix}lists SET name=? WHERE id=$id", array($name)); + $db->dq("UPDATE {$db->prefix}lists SET name=?,d_edited=? WHERE id=$id", array($name, time()) ); $t['total'] = $db->affected(); $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); $t['list'][] = prepareList($r); @@ -424,7 +426,7 @@ elseif(isset($_GET['setSort'])) $listId = (int)_post('list'); $sort = (int)_post('sort'); if($sort < 0 || $sort > 2) $sort = 0; - $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort WHERE id=$listId"); + $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort,d_edited=? WHERE id=$listId", array(time())); echo json_encode(array('total'=>1)); exit; } @@ -433,7 +435,7 @@ elseif(isset($_GET['publishList'])) check_write_access(); $listId = (int)_post('list'); $publish = (int)_post('publish'); - $db->ex("UPDATE {$db->prefix}lists SET published=? WHERE id=$listId", array($publish ? 1 : 0)); + $db->ex("UPDATE {$db->prefix}lists SET published=?,d_created=? WHERE id=$listId", array($publish ? 1 : 0, time())); echo json_encode(array('total'=>1)); exit; } @@ -464,7 +466,8 @@ elseif(isset($_GET['changeListOrder'])) $setCase .= "WHEN id=$id THEN $ow\n"; } $ids = implode($a, ','); - $db->dq("UPDATE {$db->prefix}lists SET ow = CASE\n $setCase END WHERE id IN ($ids)"); + $db->dq("UPDATE {$db->prefix}lists SET d_edited=?, ow = CASE\n $setCase END WHERE id IN ($ids)", + array(time()) ); $t['total'] = 1; } echo json_encode($t); @@ -593,7 +596,7 @@ function prepareTags($tagsStr) $aTags = array('tags'=>array(), 'ids'=>array()); foreach($tags as $tag) { - $tag = str_replace(array('"',"'",'<','>','&','/','\\'),array('','','','','','',''),trim($tag)); + $tag = str_replace(array('"',"'",'<','>','&','/','\\','^'),'',trim($tag)); if($tag == '') continue; $aTag = getOrCreateTag($tag); @@ -640,7 +643,7 @@ function addTaskTags($taskId, $tagIds, $listId) if(!$tagIds) return; foreach($tagIds as $tagId) { - $db->ex("INSERT INTO tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); + $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); } } @@ -777,7 +780,8 @@ function myErrorHandler($errno, $errstr, $errfile, $errline) function myExceptionHandler($e) { if(-1 == $e->getCode()) { - echo $e->getMessage(); exit; + echo $e->getMessage()."\n". $e->getTraceAsString(); + exit; } echo 'Exception: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine(); //."\n". $e->getTraceAsString(); exit; @@ -813,7 +817,7 @@ function moveTask($id, $listId) $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=? WHERE id=?", array($listId, $ow, $id)); + $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=?, d_edited=? WHERE id=?", array($listId, $ow, time(), $id)); $db->ex("COMMIT"); return true; } diff --git a/src/class.db.mysql.php b/src/class.db.mysql.php index b4c0742..6a77775 100644 --- a/src/class.db.mysql.php +++ b/src/class.db.mysql.php @@ -133,7 +133,7 @@ class Database_Mysql } $query = ""; for($i=0; $iquote($p[$i]); + $query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i])); } $query .= $m[$i]; } diff --git a/src/class.db.sqlite3.php b/src/class.db.sqlite3.php index 8b410b2..16d21fc 100644 --- a/src/class.db.sqlite3.php +++ b/src/class.db.sqlite3.php @@ -119,7 +119,7 @@ class Database_Sqlite3 } $query = ""; for($i=0; $iquote($p[$i]); + $query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i])); } $query .= $m[$i]; } diff --git a/src/common.php b/src/common.php index 5a447c9..b9b9d52 100644 --- a/src/common.php +++ b/src/common.php @@ -165,4 +165,16 @@ function escapeTags($s) return $s; } +/* found in comments on http://www.php.net/manual/en/function.uniqid.php#94959 */ +function generateUUID() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), + mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) + ); +} + + ?> \ No newline at end of file diff --git a/src/setup.php b/src/setup.php index 5ccd8aa..383e3e7 100644 --- a/src/setup.php +++ b/src/setup.php @@ -6,6 +6,8 @@ Licensed under the GNU GPL v3 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'])) @@ -95,22 +97,27 @@ if(!$ver) $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`) + 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_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, @@ -120,7 +127,8 @@ if(!$ver) `tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */ `duedate` DATE default NULL, PRIMARY KEY(`id`), - KEY(`list_id`) + KEY(`list_id`), + UNIQUE KEY(`uuid`) ) CHARSET=utf8 "); @@ -148,7 +156,7 @@ if(!$ver) exitMessage("Error: ". htmlarray($e->getMessage())); } } - else + else #sqlite { try { @@ -156,31 +164,37 @@ if(!$ver) $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(500) NOT NULL default '', + tags VARCHAR(600) NOT NULL default '', tags_ids VARCHAR(250) NOT NULL default '', duedate DATE default NULL ) "); - $db->ex("CREATE INDEX list_id ON {$db->prefix}todolist (list_id)"); + $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( @@ -205,8 +219,10 @@ if(!$ver) exitMessage("Error: ". htmlarray($e->getMessage())); } } + + # create default list + $db->ex("INSERT INTO {$db->prefix}lists (uuid,name,d_created) VALUES (?,?,?)", array(generateUUID(), 'Todo', time())); - createDefaultList($db); } elseif($ver == $lastVer) { @@ -214,7 +230,7 @@ elseif($ver == $lastVer) } else { - if(!in_array($ver, array('1.1','1.2','1.3.0'))) { + 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'])) { @@ -225,20 +241,27 @@ else } # 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."; @@ -266,6 +289,12 @@ function get_ver($db, $dbtype) 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; } @@ -327,6 +356,14 @@ function testConnect(&$error) 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) { @@ -442,19 +479,15 @@ function update_12_13($db, $dbtype) $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"); - createDefaultList($db); -} - -function createDefaultList($db) -{ - $db->ex("INSERT INTO {$db->prefix}lists (name,d_created) VALUES (?,?)", array('Todo', time())); - - $db->ex("UPDATE {$db->prefix}todolist SET list_id=1"); } ### end 1.2-1.3 ##### + ### 1.3.0 to 1.3.1 ########## function update_130_131($db, $dbtype) { @@ -568,4 +601,170 @@ function update_130_131($db, $dbtype) ### 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 != ''"); + while($r = $q->fetch_assoc()) + { + $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"); + while($r = $q->fetch_assoc()) { + $db->ex("UPDATE {$db->prefix}todolist SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); + } + $q = $db->dq("SELECT id FROM {$db->prefix}lists"); + while($r = $q->fetch_assoc()) { + $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