This commit is contained in:
Aleksander Machniak 2019-09-27 20:56:27 +02:00
parent 58d9ed1227
commit 357644ec9b

View file

@ -24,18 +24,17 @@
class tasklist_database_driver extends tasklist_driver class tasklist_database_driver extends tasklist_driver
{ {
const IS_COMPLETE_SQL = "(status='COMPLETED' OR (complete=1 AND status=''))"; const IS_COMPLETE_SQL = "(`status` = 'COMPLETED' OR (`complete` = 1 AND `status` = ''))";
public $undelete = true; // yes, we can public $undelete = true; // yes, we can
public $sortable = false; public $sortable = false;
public $alarm_types = array('DISPLAY'); public $alarm_types = array('DISPLAY');
private $rc; private $rc;
private $plugin; private $plugin;
private $lists = array(); private $lists = array();
private $tags = array();
private $list_ids = ''; private $list_ids = '';
private $tags = array();
private $db_tasks = 'tasks'; private $db_tasks = 'tasks';
private $db_lists = 'tasklists'; private $db_lists = 'tasklists';
@ -45,7 +44,7 @@ class tasklist_database_driver extends tasklist_driver
*/ */
public function __construct($plugin) public function __construct($plugin)
{ {
$this->rc = $plugin->rc; $this->rc = $plugin->rc;
$this->plugin = $plugin; $this->plugin = $plugin;
// read database config // read database config
@ -61,29 +60,31 @@ class tasklist_database_driver extends tasklist_driver
*/ */
private function _read_lists() private function _read_lists()
{ {
$hidden = array_filter(explode(',', $this->rc->config->get('hidden_tasklists', ''))); $hidden = array_filter(explode(',', $this->rc->config->get('hidden_tasklists', '')));
if (!empty($this->rc->user->ID)) { if (!empty($this->rc->user->ID)) {
$list_ids = array(); $list_ids = array();
$result = $this->rc->db->query( $result = $this->rc->db->query(
"SELECT *, tasklist_id AS id FROM " . $this->db_lists . " "SELECT *, `tasklist_id` AS id FROM " . $this->db_lists
WHERE user_id=? . " WHERE `user_id` = ?"
ORDER BY CASE WHEN name='INBOX' THEN 0 ELSE 1 END, name", . " ORDER BY CASE WHEN `name` = 'INBOX' THEN 0 ELSE 1 END, `name`",
$this->rc->user->ID $this->rc->user->ID
); );
while ($result && ($arr = $this->rc->db->fetch_assoc($result))) { while ($result && ($arr = $this->rc->db->fetch_assoc($result))) {
$arr['showalarms'] = intval($arr['showalarms']); $arr['showalarms'] = intval($arr['showalarms']);
$arr['active'] = !in_array($arr['id'], $hidden); $arr['active'] = !in_array($arr['id'], $hidden);
$arr['name'] = html::quote($arr['name']); $arr['name'] = html::quote($arr['name']);
$arr['listname'] = html::quote($arr['name']); $arr['listname'] = html::quote($arr['name']);
$arr['editable'] = true; $arr['editable'] = true;
$arr['rights'] = 'lrswikxtea'; $arr['rights'] = 'lrswikxtea';
$this->lists[$arr['id']] = $arr;
$list_ids[] = $this->rc->db->quote($arr['id']); $this->lists[$arr['id']] = $arr;
$list_ids[] = $this->rc->db->quote($arr['id']);
}
$this->list_ids = join(',', $list_ids);
} }
$this->list_ids = join(',', $list_ids);
}
} }
/** /**
@ -91,14 +92,15 @@ class tasklist_database_driver extends tasklist_driver
*/ */
public function get_lists($filter = 0) public function get_lists($filter = 0)
{ {
// attempt to create a default list for this user // attempt to create a default list for this user
if (empty($this->lists)) { if (empty($this->lists)) {
$prop = array('name' => 'Default', 'color' => '000000'); $prop = array('name' => 'Default', 'color' => '000000');
if ($this->create_list($prop)) if ($this->create_list($prop)) {
$this->_read_lists(); $this->_read_lists();
} }
}
return $this->lists; return $this->lists;
} }
/** /**
@ -111,17 +113,18 @@ class tasklist_database_driver extends tasklist_driver
public function create_list(&$prop) public function create_list(&$prop)
{ {
$result = $this->rc->db->query( $result = $this->rc->db->query(
"INSERT INTO " . $this->db_lists . " "INSERT INTO " . $this->db_lists
(user_id, name, color, showalarms) . " (`user_id`, `name`, `color`, `showalarms`)"
VALUES (?, ?, ?, ?)", . " VALUES (?, ?, ?, ?)",
$this->rc->user->ID, $this->rc->user->ID,
strval($prop['name']), strval($prop['name']),
strval($prop['color']), strval($prop['color']),
$prop['showalarms']?1:0 $prop['showalarms'] ? 1 : 0
); );
if ($result) if ($result) {
return $this->rc->db->insert_id($this->db_lists); return $this->rc->db->insert_id($this->db_lists);
}
return false; return false;
} }
@ -136,13 +139,11 @@ class tasklist_database_driver extends tasklist_driver
public function edit_list(&$prop) public function edit_list(&$prop)
{ {
$query = $this->rc->db->query( $query = $this->rc->db->query(
"UPDATE " . $this->db_lists . " "UPDATE " . $this->db_lists . " SET `name` = ?, `color` = ?, `showalarms` = ?"
SET name=?, color=?, showalarms=? . " WHERE `tasklist_id` = ? AND `user_id` = ?",
WHERE tasklist_id=?
AND user_id=?",
strval($prop['name']), strval($prop['name']),
strval($prop['color']), strval($prop['color']),
$prop['showalarms']?1:0, $prop['showalarms'] ? 1 : 0,
$prop['id'], $prop['id'],
$this->rc->user->ID $this->rc->user->ID
); );
@ -161,10 +162,12 @@ class tasklist_database_driver extends tasklist_driver
{ {
$hidden = array_flip(explode(',', $this->rc->config->get('hidden_tasklists', ''))); $hidden = array_flip(explode(',', $this->rc->config->get('hidden_tasklists', '')));
if ($prop['active']) if ($prop['active']) {
unset($hidden[$prop['id']]); unset($hidden[$prop['id']]);
else }
else {
$hidden[$prop['id']] = 1; $hidden[$prop['id']] = 1;
}
return $this->rc->user->save_prefs(array('hidden_tasklists' => join(',', array_keys($hidden)))); return $this->rc->user->save_prefs(array('hidden_tasklists' => join(',', array_keys($hidden))));
} }
@ -183,16 +186,13 @@ class tasklist_database_driver extends tasklist_driver
if ($this->lists[$list_id]) { if ($this->lists[$list_id]) {
// delete all tasks linked with this list // delete all tasks linked with this list
$this->rc->db->query( $this->rc->db->query(
"DELETE FROM " . $this->db_tasks . " "DELETE FROM " . $this->db_tasks . " WHERE `tasklist_id` = ?",
WHERE tasklist_id=?",
$list_id $list_id
); );
// delete list record // delete list record
$query = $this->rc->db->query( $query = $this->rc->db->query(
"DELETE FROM " . $this->db_lists . " "DELETE FROM " . $this->db_lists . " WHERE `tasklist_id` = ? AND `user_id` = ?",
WHERE tasklist_id=?
AND user_id=?",
$list_id, $list_id,
$this->rc->user->ID $this->rc->user->ID
); );
@ -234,23 +234,24 @@ class tasklist_database_driver extends tasklist_driver
*/ */
function count_tasks($lists = null) function count_tasks($lists = null)
{ {
if (empty($lists)) if (empty($lists)) {
$lists = array_keys($this->lists); $lists = array_keys($this->lists);
else if (!is_array($lists)) }
else if (!is_array($lists)) {
$lists = explode(',', (string) $lists); $lists = explode(',', (string) $lists);
}
// only allow to select from lists of this user // only allow to select from lists of this user
$list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists))); $list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists)));
$today_date = new DateTime('now', $this->plugin->timezone); $today_date = new DateTime('now', $this->plugin->timezone);
$today = $today_date->format('Y-m-d'); $today = $today_date->format('Y-m-d');
$tomorrow_date = new DateTime('now + 1 day', $this->plugin->timezone); $tomorrow_date = new DateTime('now + 1 day', $this->plugin->timezone);
$tomorrow = $tomorrow_date->format('Y-m-d'); $tomorrow = $tomorrow_date->format('Y-m-d');
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query(sprintf(
"SELECT task_id, flagged, date FROM " . $this->db_tasks . " "SELECT `task_id`, `flagged`, `date` FROM " . $this->db_tasks
WHERE tasklist_id IN (%s) . " WHERE `tasklist_id` IN (%s) AND `del` = 0 AND NOT " . self::IS_COMPLETE_SQL,
AND del=0 AND NOT " . self::IS_COMPLETE_SQL,
join(',', $list_ids) join(',', $list_ids)
)); ));
@ -277,30 +278,35 @@ class tasklist_database_driver extends tasklist_driver
* *
* @param array Hash array wiht filter criterias * @param array Hash array wiht filter criterias
* @param array List of lists to get tasks from * @param array List of lists to get tasks from
*
* @return array List of tasks records matchin the criteria * @return array List of tasks records matchin the criteria
* @see tasklist_driver::list_tasks() * @see tasklist_driver::list_tasks()
*/ */
function list_tasks($filter, $lists = null) function list_tasks($filter, $lists = null)
{ {
if (empty($lists)) if (empty($lists)) {
$lists = array_keys($this->lists); $lists = array_keys($this->lists);
else if (!is_array($lists)) }
else if (!is_array($lists)) {
$lists = explode(',', (string) $lists); $lists = explode(',', (string) $lists);
}
// only allow to select from lists of this user // only allow to select from lists of this user
$list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists))); $list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists)));
$sql_add = ''; $sql_add = '';
// add filter criteria // add filter criteria
if ($filter['from'] || ($filter['mask'] & tasklist::FILTER_MASK_TODAY)) { if ($filter['from'] || ($filter['mask'] & tasklist::FILTER_MASK_TODAY)) {
$sql_add .= ' AND (date IS NULL OR date >= ?)'; $sql_add .= " AND (`date` IS NULL OR `date` >= ?)";
$datefrom = $filter['from']; $datefrom = $filter['from'];
} }
if ($filter['to']) { if ($filter['to']) {
if ($filter['mask'] & tasklist::FILTER_MASK_OVERDUE) if ($filter['mask'] & tasklist::FILTER_MASK_OVERDUE) {
$sql_add .= ' AND (date IS NOT NULL AND date <= ' . $this->rc->db->quote($filter['to']) . ')'; $sql_add .= " AND (`date` IS NOT NULL AND `date` <= " . $this->rc->db->quote($filter['to']) . ")";
else }
$sql_add .= ' AND (date IS NULL OR date <= ' . $this->rc->db->quote($filter['to']) . ')'; else {
$sql_add .= " AND (`date` IS NULL OR `date` <= " . $this->rc->db->quote($filter['to']) . ")";
}
} }
// special case 'today': also show all events with date before today // special case 'today': also show all events with date before today
@ -308,47 +314,48 @@ class tasklist_database_driver extends tasklist_driver
$datefrom = date('Y-m-d', 0); $datefrom = date('Y-m-d', 0);
} }
if ($filter['mask'] & tasklist::FILTER_MASK_NODATE) if ($filter['mask'] & tasklist::FILTER_MASK_NODATE) {
$sql_add = ' AND date IS NULL'; $sql_add = " AND `date` IS NULL";
}
if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) {
$sql_add .= ' AND ' . self::IS_COMPLETE_SQL; $sql_add .= " AND " . self::IS_COMPLETE_SQL;
else if (empty($filter['since'])) // don't show complete tasks by default }
$sql_add .= ' AND NOT ' . self::IS_COMPLETE_SQL; else if (empty($filter['since'])) {
// don't show complete tasks by default
$sql_add .= " AND NOT " . self::IS_COMPLETE_SQL;
}
if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) {
$sql_add .= ' AND flagged=1'; $sql_add .= " AND `flagged` = 1";
}
// compose (slow) SQL query for searching // compose (slow) SQL query for searching
// FIXME: improve searching using a dedicated col and normalized values // FIXME: improve searching using a dedicated col and normalized values
if ($filter['search']) { if ($filter['search']) {
$sql_query = array(); $sql_query = array();
foreach (array('title','description','organizer','attendees') as $col) foreach (array('title', 'description', 'organizer', 'attendees') as $col) {
$sql_query[] = $this->rc->db->ilike($col, '%'.$filter['search'].'%'); $sql_query[] = $this->rc->db->ilike($col, '%' . $filter['search'] . '%');
$sql_add = 'AND (' . join(' OR ', $sql_query) . ')'; }
$sql_add = "AND (" . join(" OR ", $sql_query) . ")";
} }
if ($filter['since'] && is_numeric($filter['since'])) { if ($filter['since'] && is_numeric($filter['since'])) {
$sql_add .= ' AND changed >= ' . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since'])); $sql_add .= " AND `changed` >= " . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since']));
} }
if ($filter['uid']) { if ($filter['uid']) {
$sql_add .= ' AND `uid` IN (' . implode(',', array_map(array($this->rc->db, 'quote'), $filter['uid'])) . ')'; $sql_add .= " AND `uid` IN (" . implode(',', array_map(array($this->rc->db, 'quote'), $filter['uid'])) . ")";
} }
$tasks = array(); $tasks = array();
if (!empty($list_ids)) { if (!empty($list_ids)) {
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
"SELECT * FROM " . $this->db_tasks . " . " WHERE `tasklist_id` IN (" . join(',', $list_ids) . ")"
WHERE tasklist_id IN (%s) . " AND `del` = 0" . $sql_add
AND del=0 . " ORDER BY `parent_id`, `task_id` ASC",
%s
ORDER BY parent_id, task_id ASC",
join(',', $list_ids),
$sql_add
),
$datefrom $datefrom
); );
while ($result && ($rec = $this->rc->db->fetch_assoc($result))) { while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
$tasks[] = $this->_read_postprocess($rec); $tasks[] = $this->_read_postprocess($rec);
@ -369,20 +376,16 @@ class tasklist_database_driver extends tasklist_driver
*/ */
public function get_task($prop, $filter = 0) public function get_task($prop, $filter = 0)
{ {
if (is_string($prop)) if (is_string($prop)) {
$prop['uid'] = $prop; $prop['uid'] = $prop;
}
$query_col = $prop['id'] ? 'task_id' : 'uid'; $query_col = $prop['id'] ? 'task_id' : 'uid';
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
"SELECT * FROM " . $this->db_tasks . " . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
WHERE tasklist_id IN (%s) . " AND `$query_col` = ? AND `del` = 0",
AND %s=? $prop['id'] ? $prop['id'] : $prop['uid']
AND del=0",
$this->list_ids,
$query_col
),
$prop['id'] ? $prop['id'] : $prop['uid']
); );
if ($result && ($rec = $this->rc->db->fetch_assoc($result))) { if ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
@ -395,46 +398,46 @@ class tasklist_database_driver extends tasklist_driver
/** /**
* Get all decendents of the given task record * Get all decendents of the given task record
* *
* @param mixed Hash array with task properties or task UID * @param mixed Hash array with task properties or task UID
* @param boolean True if all childrens children should be fetched * @param boolean True if all childrens children should be fetched
*
* @return array List of all child task IDs * @return array List of all child task IDs
*/ */
public function get_childs($prop, $recursive = false) public function get_childs($prop, $recursive = false)
{ {
// resolve UID first // resolve UID first
if (is_string($prop)) { if (is_string($prop)) {
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query(
"SELECT task_id AS id, tasklist_id AS list FROM " . $this->db_tasks . " "SELECT `task_id` AS id, `tasklist_id` AS list FROM " . $this->db_tasks
WHERE tasklist_id IN (%s) . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
AND uid=?", . " AND `uid` = ?",
$this->list_ids $prop
), );
$prop);
$prop = $this->rc->db->fetch_assoc($result); $prop = $this->rc->db->fetch_assoc($result);
} }
$childs = array(); $childs = array();
$task_ids = array($prop['id']); $task_ids = array($prop['id']);
// query for childs (recursively) // query for childs (recursively)
while (!empty($task_ids)) { while (!empty($task_ids)) {
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query(
"SELECT task_id AS id FROM " . $this->db_tasks . " "SELECT `task_id` AS id FROM " . $this->db_tasks
WHERE tasklist_id IN (%s) . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
AND parent_id IN (%s) . " AND `parent_id` IN (" . join(',', array_map(array($this->rc->db, 'quote'), $task_ids)) . ")"
AND del=0", . " AND `del` = 0",
$this->list_ids, );
join(',', array_map(array($this->rc->db, 'quote'), $task_ids))
));
$task_ids = array(); $task_ids = array();
while ($result && ($rec = $this->rc->db->fetch_assoc($result))) { while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
$childs[] = $rec['id']; $childs[] = $rec['id'];
$task_ids[] = $rec['id']; $task_ids[] = $rec['id'];
} }
if (!$recursive) if (!$recursive) {
break; break;
}
} }
return $childs; return $childs;
@ -443,38 +446,41 @@ class tasklist_database_driver extends tasklist_driver
/** /**
* Get a list of pending alarms to be displayed to the user * Get a list of pending alarms to be displayed to the user
* *
* @param integer Current time (unix timestamp) * @param integer Current time (unix timestamp)
* @param mixed List of list IDs to show alarms for (either as array or comma-separated string) * @param mixed List of list IDs to show alarms for (either as array or comma-separated string)
*
* @return array A list of alarms, each encoded as hash array with task properties * @return array A list of alarms, each encoded as hash array with task properties
* @see tasklist_driver::pending_alarms() * @see tasklist_driver::pending_alarms()
*/ */
public function pending_alarms($time, $lists = null) public function pending_alarms($time, $lists = null)
{ {
if (empty($lists)) if (empty($lists)) {
$lists = array_keys($this->lists); $lists = array_keys($this->lists);
else if (!is_array($lists)) }
else if (!is_array($lists)) {
$lists = explode(',', (string) $lists); $lists = explode(',', (string) $lists);
}
// only allow to select from calendars with activated alarms // only allow to select from calendars with activated alarms
$list_ids = array(); $list_ids = array();
foreach ($lists as $lid) { foreach ($lists as $lid) {
if ($this->lists[$lid] && $this->lists[$lid]['showalarms']) if ($this->lists[$lid] && $this->lists[$lid]['showalarms']) {
$list_ids[] = $lid; $list_ids[] = $lid;
}
} }
$list_ids = array_map(array($this->rc->db, 'quote'), $list_ids); $list_ids = array_map(array($this->rc->db, 'quote'), $list_ids);
$alarms = array(); $alarms = array();
if (!empty($list_ids)) { if (!empty($list_ids)) {
$result = $this->rc->db->query(sprintf( $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
"SELECT * FROM " . $this->db_tasks . " . " WHERE `tasklist_id` IN (" . join(',', $list_ids) . ")"
WHERE tasklist_id IN (%s) . " AND `notify` <= " . $this->rc->db->fromunixtime($time)
AND notify <= %s AND NOT " . self::IS_COMPLETE_SQL, . " AND NOT " . self::IS_COMPLETE_SQL,
join(',', $list_ids), );
$this->rc->db->fromunixtime($time)
));
while ($result && ($rec = $this->rc->db->fetch_assoc($result))) while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
$alarms[] = $this->_read_postprocess($rec); $alarms[] = $this->_read_postprocess($rec);
}
} }
return $alarms; return $alarms;
@ -490,12 +496,9 @@ class tasklist_database_driver extends tasklist_driver
// set new notifyat time or unset if not snoozed // set new notifyat time or unset if not snoozed
$notify_at = $snooze > 0 ? date('Y-m-d H:i:s', time() + $snooze) : null; $notify_at = $snooze > 0 ? date('Y-m-d H:i:s', time() + $snooze) : null;
$query = $this->rc->db->query(sprintf( $query = $this->rc->db->query("UPDATE " . $this->db_tasks
"UPDATE " . $this->db_tasks . " . " SET `changed` = " . $this->rc->db->now() . ", `notify` = ?"
SET changed=%s, notify=? . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
WHERE task_id=?
AND tasklist_id IN (" . $this->list_ids . ")",
$this->rc->db->now()),
$notify_at, $notify_at,
$task_id $task_id
); );
@ -518,13 +521,14 @@ class tasklist_database_driver extends tasklist_driver
*/ */
private function _read_postprocess($rec) private function _read_postprocess($rec)
{ {
$rec['id'] = $rec['task_id']; $rec['id'] = $rec['task_id'];
$rec['list'] = $rec['tasklist_id']; $rec['list'] = $rec['tasklist_id'];
$rec['changed'] = new DateTime($rec['changed']); $rec['changed'] = new DateTime($rec['changed']);
$rec['tags'] = array_filter(explode(',', $rec['tags'])); $rec['tags'] = array_filter(explode(',', $rec['tags']));
if (!$rec['parent_id']) if (!$rec['parent_id']) {
unset($rec['parent_id']); unset($rec['parent_id']);
}
// decode serialized alarms // decode serialized alarms
if ($rec['alarms']) { if ($rec['alarms']) {
@ -542,6 +546,7 @@ class tasklist_database_driver extends tasklist_driver
} }
unset($rec['task_id'], $rec['tasklist_id'], $rec['created']); unset($rec['task_id'], $rec['tasklist_id'], $rec['created']);
return $rec; return $rec;
} }
@ -549,6 +554,7 @@ class tasklist_database_driver extends tasklist_driver
* Add a single task to the database * Add a single task to the database
* *
* @param array Hash array with task properties (see header of this file) * @param array Hash array with task properties (see header of this file)
*
* @return mixed New event ID on success, False on error * @return mixed New event ID on success, False on error
* @see tasklist_driver::create_task() * @see tasklist_driver::create_task()
*/ */
@ -556,8 +562,9 @@ class tasklist_database_driver extends tasklist_driver
{ {
// check list permissions // check list permissions
$list_id = $prop['list'] ? $prop['list'] : reset(array_keys($this->lists)); $list_id = $prop['list'] ? $prop['list'] : reset(array_keys($this->lists));
if (!$this->lists[$list_id] || $this->lists[$list_id]['readonly']) if (!$this->lists[$list_id] || $this->lists[$list_id]['readonly']) {
return false; return false;
}
if (is_array($prop['valarms'])) { if (is_array($prop['valarms'])) {
$prop['alarms'] = $this->serialize_alarms($prop['valarms']); $prop['alarms'] = $this->serialize_alarms($prop['valarms']);
@ -570,18 +577,19 @@ class tasklist_database_driver extends tasklist_driver
} }
foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status') as $col) { foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status') as $col) {
if (empty($prop[$col])) if (empty($prop[$col])) {
$prop[$col] = null; $prop[$col] = null;
}
} }
$notify_at = $this->_get_notification($prop); $notify_at = $this->_get_notification($prop);
$result = $this->rc->db->query(sprintf( $now = $this->rc->db->now();
"INSERT INTO " . $this->db_tasks . "
(tasklist_id, uid, parent_id, created, changed, title, date, time, startdate, starttime, description, tags, flagged, complete, status, alarms, recurrence, notify) $result = $this->rc->db->query("INSERT INTO " . $this->db_tasks
VALUES (?, ?, ?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", . " (`tasklist_id`, `uid`, `parent_id`, `created`, `changed`, `title`, `date`, `time`,"
$this->rc->db->now(), . " `startdate`, `starttime`, `description`, `tags`, `flagged`, `complete`, `status`,"
$this->rc->db->now() . " `alarms`, `recurrence`, `notify`)"
), . " VALUES (?, ?, ?, $now, $now, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
$list_id, $list_id,
$prop['uid'], $prop['uid'],
$prop['parent_id'], $prop['parent_id'],
@ -600,8 +608,9 @@ class tasklist_database_driver extends tasklist_driver
$notify_at $notify_at
); );
if ($result) if ($result) {
return $this->rc->db->insert_id($this->db_tasks); return $this->rc->db->insert_id($this->db_tasks);
}
return false; return false;
} }
@ -610,6 +619,7 @@ class tasklist_database_driver extends tasklist_driver
* Update an task entry with the given data * Update an task entry with the given data
* *
* @param array Hash array with task properties * @param array Hash array with task properties
*
* @return boolean True on success, False on error * @return boolean True on success, False on error
* @see tasklist_driver::edit_task() * @see tasklist_driver::edit_task()
*/ */
@ -627,15 +637,18 @@ class tasklist_database_driver extends tasklist_driver
$sql_set = array(); $sql_set = array();
foreach (array('title', 'description', 'flagged', 'complete') as $col) { foreach (array('title', 'description', 'flagged', 'complete') as $col) {
if (isset($prop[$col])) if (isset($prop[$col])) {
$sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($prop[$col]); $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($prop[$col]);
}
} }
foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status') as $col) { foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status') as $col) {
if (isset($prop[$col])) if (isset($prop[$col])) {
$sql_set[] = $this->rc->db->quote_identifier($col) . '=' . (empty($prop[$col]) ? 'NULL' : $this->rc->db->quote($prop[$col])); $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . (empty($prop[$col]) ? 'NULL' : $this->rc->db->quote($prop[$col]));
}
} }
if (isset($prop['tags'])) if (isset($prop['tags'])) {
$sql_set[] = $this->rc->db->quote_identifier('tags') . '=' . $this->rc->db->quote(join(',', (array)$prop['tags'])); $sql_set[] = $this->rc->db->quote_identifier('tags') . '=' . $this->rc->db->quote(join(',', (array)$prop['tags']));
}
if (isset($prop['date']) || isset($prop['time']) || isset($prop['alarms'])) { if (isset($prop['date']) || isset($prop['time']) || isset($prop['alarms'])) {
$notify_at = $this->_get_notification($prop); $notify_at = $this->_get_notification($prop);
@ -644,28 +657,23 @@ class tasklist_database_driver extends tasklist_driver
// moved from another list // moved from another list
if ($prop['_fromlist'] && ($newlist = $prop['list'])) { if ($prop['_fromlist'] && ($newlist = $prop['list'])) {
$sql_set[] = 'tasklist_id=' . $this->rc->db->quote($newlist); $sql_set[] = $this->rc->db->quote_identifier('tasklist_id') . '=' . $this->rc->db->quote($newlist);
} }
$query = $this->rc->db->query(sprintf( $result = $this->rc->db->query("UPDATE " . $this->db_tasks
"UPDATE " . $this->db_tasks . " . " SET `changed` = " . $this->rc->db->now() . ($sql_set ? ', ' . join(', ', $sql_set) : '')
SET changed=%s %s . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
WHERE task_id=? $prop['id']
AND tasklist_id IN (%s)",
$this->rc->db->now(),
($sql_set ? ', ' . join(', ', $sql_set) : ''),
$this->list_ids
),
$prop['id']
); );
return $this->rc->db->affected_rows($query); return $this->rc->db->affected_rows($result);
} }
/** /**
* Move a single task to another list * Move a single task to another list
* *
* @param array Hash array with task properties: * @param array Hash array with task properties
*
* @return boolean True on success, False on error * @return boolean True on success, False on error
* @see tasklist_driver::move_task() * @see tasklist_driver::move_task()
*/ */
@ -679,6 +687,7 @@ class tasklist_database_driver extends tasklist_driver
* *
* @param array Hash array with task properties * @param array Hash array with task properties
* @param boolean Remove record irreversible * @param boolean Remove record irreversible
*
* @return boolean True on success, False on error * @return boolean True on success, False on error
* @see tasklist_driver::delete_task() * @see tasklist_driver::delete_task()
*/ */
@ -687,50 +696,39 @@ class tasklist_database_driver extends tasklist_driver
$task_id = $prop['id']; $task_id = $prop['id'];
if ($task_id && $force) { if ($task_id && $force) {
$query = $this->rc->db->query( $result = $this->rc->db->query("DELETE FROM " . $this->db_tasks
"DELETE FROM " . $this->db_tasks . " . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
WHERE task_id=?
AND tasklist_id IN (" . $this->list_ids . ")",
$task_id $task_id
); );
} }
else if ($task_id) { else if ($task_id) {
$query = $this->rc->db->query(sprintf( $result = $this->rc->db->query("UPDATE " . $this->db_tasks
"UPDATE " . $this->db_tasks . " . " SET `changed` = " . $this->rc->db->now() . ", `del` = 1"
SET changed=%s, del=1 . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
WHERE task_id=? $task_id
AND tasklist_id IN (%s)",
$this->rc->db->now(),
$this->list_ids
),
$task_id
); );
} }
return $this->rc->db->affected_rows($query); return $this->rc->db->affected_rows($result);
} }
/** /**
* Restores a single deleted task (if supported) * Restores a single deleted task (if supported)
* *
* @param array Hash array with task properties * @param array Hash array with task properties
*
* @return boolean True on success, False on error * @return boolean True on success, False on error
* @see tasklist_driver::undelete_task() * @see tasklist_driver::undelete_task()
*/ */
public function undelete_task($prop) public function undelete_task($prop)
{ {
$query = $this->rc->db->query(sprintf( $result = $this->rc->db->query("UPDATE " . $this->db_tasks
"UPDATE " . $this->db_tasks . " . " SET `changed` = " . $this->rc->db->now() . ", `del` = 0"
SET changed=%s, del=0 . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
WHERE task_id=? $prop['id']
AND tasklist_id IN (%s)",
$this->rc->db->now(),
$this->list_ids
),
$prop['id']
); );
return $this->rc->db->affected_rows($query); return $this->rc->db->affected_rows($result);
} }
/** /**
@ -741,11 +739,10 @@ class tasklist_database_driver extends tasklist_driver
if ($task['valarms'] && !$this->is_complete($task)) { if ($task['valarms'] && !$this->is_complete($task)) {
$alarm = libcalendaring::get_next_alarm($task, 'task'); $alarm = libcalendaring::get_next_alarm($task, 'task');
if ($alarm['time'] && in_array($alarm['action'], $this->alarm_types)) if ($alarm['time'] && in_array($alarm['action'], $this->alarm_types)) {
return date('Y-m-d H:i:s', $alarm['time']); return date('Y-m-d H:i:s', $alarm['time']);
} }
}
return null;
} }
/** /**
@ -837,15 +834,17 @@ class tasklist_database_driver extends tasklist_driver
public function user_delete($args) public function user_delete($args)
{ {
$db = $this->rc->db; $db = $this->rc->db;
$lists = $db->query("SELECT `tasklist_id` FROM " . $this->db_lists . " WHERE `user_id` = ?", $args['user']->ID);
$list_ids = array(); $list_ids = array();
$lists = $db->query("SELECT tasklist_id FROM " . $this->db_lists . " WHERE user_id=?", $args['user']->ID);
while ($row = $db->fetch_assoc($lists)) { while ($row = $db->fetch_assoc($lists)) {
$list_ids[] = $row['tasklist_id']; $list_ids[] = $row['tasklist_id'];
} }
if (!empty($list_ids)) { if (!empty($list_ids)) {
foreach (array($this->db_tasks, $this->db_lists) as $table) { foreach (array($this->db_tasks, $this->db_lists) as $table) {
$db->query(sprintf("DELETE FROM $table WHERE tasklist_id IN (%s)", join(',', $list_ids))); $db->query(sprintf("DELETE FROM $table WHERE `tasklist_id` IN (%s)", join(',', $list_ids)));
} }
} }
} }