Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117883665
tasklist_database_driver.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
26 KB
Referenced Files
None
Subscribers
None
tasklist_database_driver.php
View Options
<?php
/**
* Database driver for the Tasklist plugin
*
* @version @package_version@
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2012-2015, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class
tasklist_database_driver
extends
tasklist_driver
{
const
IS_COMPLETE_SQL
=
"(status='COMPLETED' OR (complete=1 AND status=''))"
;
public
$undelete
=
true
;
// yes, we can
public
$sortable
=
false
;
public
$alarm_types
=
array
(
'DISPLAY'
);
private
$rc
;
private
$plugin
;
private
$lists
=
array
();
private
$list_ids
=
''
;
private
$tags
=
array
();
private
$db_tasks
=
'tasks'
;
private
$db_lists
=
'tasklists'
;
/**
* Default constructor
*/
public
function
__construct
(
$plugin
)
{
$this
->
rc
=
$plugin
->
rc
;
$this
->
plugin
=
$plugin
;
// read database config
$db
=
$this
->
rc
->
get_dbh
();
$this
->
db_lists
=
$this
->
rc
->
config
->
get
(
'db_table_lists'
,
$db
->
table_name
(
$this
->
db_lists
));
$this
->
db_tasks
=
$this
->
rc
->
config
->
get
(
'db_table_tasks'
,
$db
->
table_name
(
$this
->
db_tasks
));
$this
->
_read_lists
();
}
/**
* Read available calendars for the current user and store them internally
*/
private
function
_read_lists
()
{
$hidden
=
array_filter
(
explode
(
','
,
$this
->
rc
->
config
->
get
(
'hidden_tasklists'
,
''
)));
if
(!
empty
(
$this
->
rc
->
user
->
ID
))
{
$list_ids
=
array
();
$result
=
$this
->
rc
->
db
->
query
(
"SELECT *, tasklist_id AS id FROM "
.
$this
->
db_lists
.
"
WHERE user_id=?
ORDER BY CASE WHEN name='INBOX' THEN 0 ELSE 1 END, name"
,
$this
->
rc
->
user
->
ID
);
while
(
$result
&&
(
$arr
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
{
$arr
[
'showalarms'
]
=
intval
(
$arr
[
'showalarms'
]);
$arr
[
'active'
]
=
!
in_array
(
$arr
[
'id'
],
$hidden
);
$arr
[
'name'
]
=
html
::
quote
(
$arr
[
'name'
]);
$arr
[
'listname'
]
=
html
::
quote
(
$arr
[
'name'
]);
$arr
[
'editable'
]
=
true
;
$arr
[
'rights'
]
=
'lrswikxtea'
;
$this
->
lists
[
$arr
[
'id'
]]
=
$arr
;
$list_ids
[]
=
$this
->
rc
->
db
->
quote
(
$arr
[
'id'
]);
}
$this
->
list_ids
=
join
(
','
,
$list_ids
);
}
}
/**
* Get a list of available tasks lists from this source
*/
public
function
get_lists
()
{
// attempt to create a default list for this user
if
(
empty
(
$this
->
lists
))
{
$prop
=
array
(
'name'
=>
'Default'
,
'color'
=>
'000000'
);
if
(
$this
->
create_list
(
$prop
))
$this
->
_read_lists
();
}
return
$this
->
lists
;
}
/**
* Create a new list assigned to the current user
*
* @param array Hash array with list properties
* @return mixed ID of the new list on success, False on error
* @see tasklist_driver::create_list()
*/
public
function
create_list
(&
$prop
)
{
$result
=
$this
->
rc
->
db
->
query
(
"INSERT INTO "
.
$this
->
db_lists
.
"
(user_id, name, color, showalarms)
VALUES (?, ?, ?, ?)"
,
$this
->
rc
->
user
->
ID
,
strval
(
$prop
[
'name'
]),
strval
(
$prop
[
'color'
]),
$prop
[
'showalarms'
]?
1
:
0
);
if
(
$result
)
return
$this
->
rc
->
db
->
insert_id
(
$this
->
db_lists
);
return
false
;
}
/**
* Update properties of an existing tasklist
*
* @param array Hash array with list properties
* @return boolean True on success, Fales on failure
* @see tasklist_driver::edit_list()
*/
public
function
edit_list
(&
$prop
)
{
$query
=
$this
->
rc
->
db
->
query
(
"UPDATE "
.
$this
->
db_lists
.
"
SET name=?, color=?, showalarms=?
WHERE tasklist_id=?
AND user_id=?"
,
$prop
[
'name'
],
$prop
[
'color'
],
$prop
[
'showalarms'
]?
1
:
0
,
$prop
[
'id'
],
$this
->
rc
->
user
->
ID
);
return
$this
->
rc
->
db
->
affected_rows
(
$query
);
}
/**
* Set active/subscribed state of a list
*
* @param array Hash array with list properties
* @return boolean True on success, Fales on failure
* @see tasklist_driver::subscribe_list()
*/
public
function
subscribe_list
(
$prop
)
{
$hidden
=
array_flip
(
explode
(
','
,
$this
->
rc
->
config
->
get
(
'hidden_tasklists'
,
''
)));
if
(
$prop
[
'active'
])
unset
(
$hidden
[
$prop
[
'id'
]]);
else
$hidden
[
$prop
[
'id'
]]
=
1
;
return
$this
->
rc
->
user
->
save_prefs
(
array
(
'hidden_tasklists'
=>
join
(
','
,
array_keys
(
$hidden
))));
}
/**
* Delete the given list with all its contents
*
* @param array Hash array with list properties
* @return boolean True on success, Fales on failure
* @see tasklist_driver::delete_list()
*/
public
function
delete_list
(
$prop
)
{
$list_id
=
$prop
[
'id'
];
if
(
$this
->
lists
[
$list_id
])
{
// delete all tasks linked with this list
$this
->
rc
->
db
->
query
(
"DELETE FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id=?"
,
$list_id
);
// delete list record
$query
=
$this
->
rc
->
db
->
query
(
"DELETE FROM "
.
$this
->
db_lists
.
"
WHERE tasklist_id=?
AND user_id=?"
,
$list_id
,
$this
->
rc
->
user
->
ID
);
return
$this
->
rc
->
db
->
affected_rows
(
$query
);
}
return
false
;
}
/**
* Search for shared or otherwise not listed tasklists the user has access
*
* @param string Search string
* @param string Section/source to search
* @return array List of tasklists
*/
public
function
search_lists
(
$query
,
$source
)
{
return
array
();
}
/**
* Get a list of tags to assign tasks to
*
* @return array List of tags
*/
public
function
get_tags
()
{
return
array_values
(
array_unique
(
$this
->
tags
,
SORT_STRING
));
}
/**
* Get number of tasks matching the given filter
*
* @param array List of lists to count tasks of
* @return array Hash array with counts grouped by status (all|flagged|today|tomorrow|overdue|nodate)
* @see tasklist_driver::count_tasks()
*/
function
count_tasks
(
$lists
=
null
)
{
if
(
empty
(
$lists
))
$lists
=
array_keys
(
$this
->
lists
);
else
if
(
is_string
(
$lists
))
$lists
=
explode
(
','
,
$lists
);
// 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
)));
$today_date
=
new
DateTime
(
'now'
,
$this
->
plugin
->
timezone
);
$today
=
$today_date
->
format
(
'Y-m-d'
);
$tomorrow_date
=
new
DateTime
(
'now + 1 day'
,
$this
->
plugin
->
timezone
);
$tomorrow
=
$tomorrow_date
->
format
(
'Y-m-d'
);
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT task_id, flagged, date FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND del=0 AND NOT "
.
self
::
IS_COMPLETE_SQL
,
join
(
','
,
$list_ids
)
));
$counts
=
array
(
'all'
=>
0
,
'flagged'
=>
0
,
'today'
=>
0
,
'tomorrow'
=>
0
,
'overdue'
=>
0
,
'nodate'
=>
0
);
while
(
$result
&&
(
$rec
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
{
$counts
[
'all'
]++;
if
(
$rec
[
'flagged'
])
$counts
[
'flagged'
]++;
if
(
empty
(
$rec
[
'date'
]))
$counts
[
'nodate'
]++;
else
if
(
$rec
[
'date'
]
==
$today
)
$counts
[
'today'
]++;
else
if
(
$rec
[
'date'
]
==
$tomorrow
)
$counts
[
'tomorrow'
]++;
else
if
(
$rec
[
'date'
]
<
$today
)
$counts
[
'overdue'
]++;
}
return
$counts
;
}
/**
* Get all taks records matching the given filter
*
* @param array Hash array wiht filter criterias
* @param array List of lists to get tasks from
* @return array List of tasks records matchin the criteria
* @see tasklist_driver::list_tasks()
*/
function
list_tasks
(
$filter
,
$lists
=
null
)
{
if
(
empty
(
$lists
))
$lists
=
array_keys
(
$this
->
lists
);
else
if
(
is_string
(
$lists
))
$lists
=
explode
(
','
,
$lists
);
// 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
)));
$sql_add
=
''
;
// add filter criteria
if
(
$filter
[
'from'
]
||
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_TODAY
))
{
$sql_add
.=
' AND (date IS NULL OR date >= ?)'
;
$datefrom
=
$filter
[
'from'
];
}
if
(
$filter
[
'to'
])
{
if
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_OVERDUE
)
$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'
])
.
')'
;
}
// special case 'today': also show all events with date before today
if
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_TODAY
)
{
$datefrom
=
date
(
'Y-m-d'
,
0
);
}
if
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_NODATE
)
$sql_add
=
' AND date IS NULL'
;
if
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_COMPLETE
)
$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
;
if
(
$filter
[
'mask'
]
&
tasklist
::
FILTER_MASK_FLAGGED
)
$sql_add
.=
' AND flagged=1'
;
// compose (slow) SQL query for searching
// FIXME: improve searching using a dedicated col and normalized values
if
(
$filter
[
'search'
])
{
$sql_query
=
array
();
foreach
(
array
(
'title'
,
'description'
,
'organizer'
,
'attendees'
)
as
$col
)
$sql_query
[]
=
$this
->
rc
->
db
->
ilike
(
$col
,
'%'
.
$filter
[
'search'
].
'%'
);
$sql_add
=
'AND ('
.
join
(
' OR '
,
$sql_query
)
.
')'
;
}
if
(
$filter
[
'since'
]
&&
is_numeric
(
$filter
[
'since'
]))
{
$sql_add
.=
' AND changed >= '
.
$this
->
rc
->
db
->
quote
(
date
(
'Y-m-d H:i:s'
,
$filter
[
'since'
]));
}
$tasks
=
array
();
if
(!
empty
(
$list_ids
))
{
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT * FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND del=0
%s
ORDER BY parent_id, task_id ASC"
,
join
(
','
,
$list_ids
),
$sql_add
),
$datefrom
);
while
(
$result
&&
(
$rec
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
{
$tasks
[]
=
$this
->
_read_postprocess
(
$rec
);
}
}
return
$tasks
;
}
/**
* Return data of a specific task
*
* @param mixed Hash array with task properties or task UID
* @return array Hash array with task properties or false if not found
*/
public
function
get_task
(
$prop
)
{
if
(
is_string
(
$prop
))
$prop
[
'uid'
]
=
$prop
;
$query_col
=
$prop
[
'id'
]
?
'task_id'
:
'uid'
;
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT * FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND %s=?
AND del=0"
,
$this
->
list_ids
,
$query_col
),
$prop
[
'id'
]
?
$prop
[
'id'
]
:
$prop
[
'uid'
]
);
if
(
$result
&&
(
$rec
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
{
return
$this
->
_read_postprocess
(
$rec
);
}
return
false
;
}
/**
* Get all decendents of the given task record
*
* @param mixed Hash array with task properties or task UID
* @param boolean True if all childrens children should be fetched
* @return array List of all child task IDs
*/
public
function
get_childs
(
$prop
,
$recursive
=
false
)
{
// resolve UID first
if
(
is_string
(
$prop
))
{
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT task_id AS id, tasklist_id AS list FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND uid=?"
,
$this
->
list_ids
),
$prop
);
$prop
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
);
}
$childs
=
array
();
$task_ids
=
array
(
$prop
[
'id'
]);
// query for childs (recursively)
while
(!
empty
(
$task_ids
))
{
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT task_id AS id FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND parent_id IN (%s)
AND del=0"
,
$this
->
list_ids
,
join
(
','
,
array_map
(
array
(
$this
->
rc
->
db
,
'quote'
),
$task_ids
))
));
$task_ids
=
array
();
while
(
$result
&&
(
$rec
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
{
$childs
[]
=
$rec
[
'id'
];
$task_ids
[]
=
$rec
[
'id'
];
}
if
(!
$recursive
)
break
;
}
return
$childs
;
}
/**
* Get a list of pending alarms to be displayed to the user
*
* @param integer Current time (unix timestamp)
* @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
* @see tasklist_driver::pending_alarms()
*/
public
function
pending_alarms
(
$time
,
$lists
=
null
)
{
if
(
empty
(
$lists
))
$lists
=
array_keys
(
$this
->
lists
);
else
if
(
is_string
(
$lists
))
$lists
=
explode
(
','
,
$lists
);
// only allow to select from calendars with activated alarms
$list_ids
=
array
();
foreach
(
$lists
as
$lid
)
{
if
(
$this
->
lists
[
$lid
]
&&
$this
->
lists
[
$lid
][
'showalarms'
])
$list_ids
[]
=
$lid
;
}
$list_ids
=
array_map
(
array
(
$this
->
rc
->
db
,
'quote'
),
$list_ids
);
$alarms
=
array
();
if
(!
empty
(
$list_ids
))
{
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"SELECT * FROM "
.
$this
->
db_tasks
.
"
WHERE tasklist_id IN (%s)
AND notify <= %s AND NOT "
.
self
::
IS_COMPLETE_SQL
,
join
(
','
,
$list_ids
),
$this
->
rc
->
db
->
fromunixtime
(
$time
)
));
while
(
$result
&&
(
$rec
=
$this
->
rc
->
db
->
fetch_assoc
(
$result
)))
$alarms
[]
=
$this
->
_read_postprocess
(
$rec
);
}
return
$alarms
;
}
/**
* Feedback after showing/sending an alarm notification
*
* @see tasklist_driver::dismiss_alarm()
*/
public
function
dismiss_alarm
(
$task_id
,
$snooze
=
0
)
{
// set new notifyat time or unset if not snoozed
$notify_at
=
$snooze
>
0
?
date
(
'Y-m-d H:i:s'
,
time
()
+
$snooze
)
:
null
;
$query
=
$this
->
rc
->
db
->
query
(
sprintf
(
"UPDATE "
.
$this
->
db_tasks
.
"
SET changed=%s, notify=?
WHERE task_id=?
AND tasklist_id IN ("
.
$this
->
list_ids
.
")"
,
$this
->
rc
->
db
->
now
()),
$notify_at
,
$task_id
);
return
$this
->
rc
->
db
->
affected_rows
(
$query
);
}
/**
* Remove alarm dismissal or snooze state
*
* @param string Task identifier
*/
public
function
clear_alarms
(
$id
)
{
// Nothing to do here. Alarms are reset in edit_task()
}
/**
* Map some internal database values to match the generic "API"
*/
private
function
_read_postprocess
(
$rec
)
{
$rec
[
'id'
]
=
$rec
[
'task_id'
];
$rec
[
'list'
]
=
$rec
[
'tasklist_id'
];
$rec
[
'changed'
]
=
new
DateTime
(
$rec
[
'changed'
]);
$rec
[
'tags'
]
=
array_filter
(
explode
(
','
,
$rec
[
'tags'
]));
if
(!
$rec
[
'parent_id'
])
unset
(
$rec
[
'parent_id'
]);
// decode serialized alarms
if
(
$rec
[
'alarms'
])
{
$rec
[
'valarms'
]
=
$this
->
unserialize_alarms
(
$rec
[
'alarms'
]);
unset
(
$rec
[
'alarms'
]);
}
// decode serialze recurrence rules
if
(
$rec
[
'recurrence'
])
{
$rec
[
'recurrence'
]
=
$this
->
unserialize_recurrence
(
$rec
[
'recurrence'
]);
}
if
(!
empty
(
$rec
[
'tags'
]))
{
$this
->
tags
=
array_merge
(
$this
->
tags
,
(
array
)
$rec
[
'tags'
]);
}
unset
(
$rec
[
'task_id'
],
$rec
[
'tasklist_id'
],
$rec
[
'created'
]);
return
$rec
;
}
/**
* Add a single task to the database
*
* @param array Hash array with task properties (see header of this file)
* @return mixed New event ID on success, False on error
* @see tasklist_driver::create_task()
*/
public
function
create_task
(
$prop
)
{
// check list permissions
$list_id
=
$prop
[
'list'
]
?
$prop
[
'list'
]
:
reset
(
array_keys
(
$this
->
lists
));
if
(!
$this
->
lists
[
$list_id
]
||
$this
->
lists
[
$list_id
][
'readonly'
])
return
false
;
if
(
is_array
(
$prop
[
'valarms'
]))
{
$prop
[
'alarms'
]
=
$this
->
serialize_alarms
(
$prop
[
'valarms'
]);
}
if
(
is_array
(
$prop
[
'recurrence'
]))
{
$prop
[
'recurrence'
]
=
$this
->
serialize_recurrence
(
$prop
[
'recurrence'
]);
}
foreach
(
array
(
'parent_id'
,
'date'
,
'time'
,
'startdate'
,
'starttime'
,
'alarms'
,
'recurrence'
,
'status'
)
as
$col
)
{
if
(
empty
(
$prop
[
$col
]))
$prop
[
$col
]
=
null
;
}
$notify_at
=
$this
->
_get_notification
(
$prop
);
$result
=
$this
->
rc
->
db
->
query
(
sprintf
(
"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)
VALUES (?, ?, ?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
,
$this
->
rc
->
db
->
now
(),
$this
->
rc
->
db
->
now
()
),
$list_id
,
$prop
[
'uid'
],
$prop
[
'parent_id'
],
$prop
[
'title'
],
$prop
[
'date'
],
$prop
[
'time'
],
$prop
[
'startdate'
],
$prop
[
'starttime'
],
strval
(
$prop
[
'description'
]),
join
(
','
,
(
array
)
$prop
[
'tags'
]),
$prop
[
'flagged'
]
?
1
:
0
,
intval
(
$prop
[
'complete'
]),
$prop
[
'status'
],
$prop
[
'alarms'
],
$prop
[
'recurrence'
],
$notify_at
);
if
(
$result
)
return
$this
->
rc
->
db
->
insert_id
(
$this
->
db_tasks
);
return
false
;
}
/**
* Update an task entry with the given data
*
* @param array Hash array with task properties
* @return boolean True on success, False on error
* @see tasklist_driver::edit_task()
*/
public
function
edit_task
(
$prop
)
{
if
(
is_array
(
$prop
[
'valarms'
]))
{
$prop
[
'alarms'
]
=
$this
->
serialize_alarms
(
$prop
[
'valarms'
]);
}
if
(
is_array
(
$prop
[
'recurrence'
]))
{
$prop
[
'recurrence'
]
=
$this
->
serialize_recurrence
(
$prop
[
'recurrence'
]);
}
$sql_set
=
array
();
foreach
(
array
(
'title'
,
'description'
,
'flagged'
,
'complete'
)
as
$col
)
{
if
(
isset
(
$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
)
{
if
(
isset
(
$prop
[
$col
]))
$sql_set
[]
=
$this
->
rc
->
db
->
quote_identifier
(
$col
)
.
'='
.
(
empty
(
$prop
[
$col
])
?
'NULL'
:
$this
->
rc
->
db
->
quote
(
$prop
[
$col
]));
}
if
(
isset
(
$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'
]))
{
$notify_at
=
$this
->
_get_notification
(
$prop
);
$sql_set
[]
=
$this
->
rc
->
db
->
quote_identifier
(
'notify'
)
.
'='
.
(
empty
(
$notify_at
)
?
'NULL'
:
$this
->
rc
->
db
->
quote
(
$notify_at
));
}
// moved from another list
if
(
$prop
[
'_fromlist'
]
&&
(
$newlist
=
$prop
[
'list'
]))
{
$sql_set
[]
=
'tasklist_id='
.
$this
->
rc
->
db
->
quote
(
$newlist
);
}
$query
=
$this
->
rc
->
db
->
query
(
sprintf
(
"UPDATE "
.
$this
->
db_tasks
.
"
SET changed=%s %s
WHERE task_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
);
}
/**
* Move a single task to another list
*
* @param array Hash array with task properties:
* @return boolean True on success, False on error
* @see tasklist_driver::move_task()
*/
public
function
move_task
(
$prop
)
{
return
$this
->
edit_task
(
$prop
);
}
/**
* Remove a single task from the database
*
* @param array Hash array with task properties
* @param boolean Remove record irreversible
* @return boolean True on success, False on error
* @see tasklist_driver::delete_task()
*/
public
function
delete_task
(
$prop
,
$force
=
true
)
{
$task_id
=
$prop
[
'id'
];
if
(
$task_id
&&
$force
)
{
$query
=
$this
->
rc
->
db
->
query
(
"DELETE FROM "
.
$this
->
db_tasks
.
"
WHERE task_id=?
AND tasklist_id IN ("
.
$this
->
list_ids
.
")"
,
$task_id
);
}
else
if
(
$task_id
)
{
$query
=
$this
->
rc
->
db
->
query
(
sprintf
(
"UPDATE "
.
$this
->
db_tasks
.
"
SET changed=%s, del=1
WHERE task_id=?
AND tasklist_id IN (%s)"
,
$this
->
rc
->
db
->
now
(),
$this
->
list_ids
),
$task_id
);
}
return
$this
->
rc
->
db
->
affected_rows
(
$query
);
}
/**
* Restores a single deleted task (if supported)
*
* @param array Hash array with task properties
* @return boolean True on success, False on error
* @see tasklist_driver::undelete_task()
*/
public
function
undelete_task
(
$prop
)
{
$query
=
$this
->
rc
->
db
->
query
(
sprintf
(
"UPDATE "
.
$this
->
db_tasks
.
"
SET changed=%s, del=0
WHERE task_id=?
AND tasklist_id IN (%s)"
,
$this
->
rc
->
db
->
now
(),
$this
->
list_ids
),
$prop
[
'id'
]
);
return
$this
->
rc
->
db
->
affected_rows
(
$query
);
}
/**
* Compute absolute time to notify the user
*/
private
function
_get_notification
(
$task
)
{
if
(
$task
[
'valarms'
]
&&
!
$this
->
is_complete
(
$task
))
{
$alarm
=
libcalendaring
::
get_next_alarm
(
$task
,
'task'
);
if
(
$alarm
[
'time'
]
&&
in_array
(
$alarm
[
'action'
],
$this
->
alarm_types
))
return
date
(
'Y-m-d H:i:s'
,
$alarm
[
'time'
]);
}
return
null
;
}
/**
* Helper method to serialize the list of alarms into a string
*/
private
function
serialize_alarms
(
$valarms
)
{
foreach
((
array
)
$valarms
as
$i
=>
$alarm
)
{
if
(
$alarm
[
'trigger'
]
instanceof
DateTime
)
{
$valarms
[
$i
][
'trigger'
]
=
'@'
.
$alarm
[
'trigger'
]->
format
(
'c'
);
}
}
return
$valarms
?
json_encode
(
$valarms
)
:
null
;
}
/**
* Helper method to decode a serialized list of alarms
*/
private
function
unserialize_alarms
(
$alarms
)
{
// decode json serialized alarms
if
(
$alarms
&&
$alarms
[
0
]
==
'['
)
{
$valarms
=
json_decode
(
$alarms
,
true
);
foreach
(
$valarms
as
$i
=>
$alarm
)
{
if
(
$alarm
[
'trigger'
][
0
]
==
'@'
)
{
try
{
$valarms
[
$i
][
'trigger'
]
=
new
DateTime
(
substr
(
$alarm
[
'trigger'
],
1
));
}
catch
(
Exception
$e
)
{
unset
(
$valarms
[
$i
]);
}
}
}
}
// convert legacy alarms data
else
if
(
strlen
(
$alarms
))
{
list
(
$trigger
,
$action
)
=
explode
(
':'
,
$alarms
,
2
);
if
(
$trigger
=
libcalendaring
::
parse_alarm_value
(
$trigger
))
{
$valarms
=
array
(
array
(
'action'
=>
$action
,
'trigger'
=>
$trigger
[
3
]
?:
$trigger
[
0
]));
}
}
return
$valarms
;
}
/**
* Helper method to serialize task recurrence properties
*/
private
function
serialize_recurrence
(
$recurrence
)
{
foreach
((
array
)
$recurrence
as
$k
=>
$val
)
{
if
(
$val
instanceof
DateTime
)
{
$recurrence
[
$k
]
=
'@'
.
$val
->
format
(
'c'
);
}
}
return
$recurrence
?
json_encode
(
$recurrence
)
:
null
;
}
/**
* Helper method to decode a serialized task recurrence struct
*/
private
function
unserialize_recurrence
(
$ser
)
{
if
(
strlen
(
$ser
))
{
$recurrence
=
json_decode
(
$ser
,
true
);
foreach
((
array
)
$recurrence
as
$k
=>
$val
)
{
if
(
$val
[
0
]
==
'@'
)
{
try
{
$recurrence
[
$k
]
=
new
DateTime
(
substr
(
$val
,
1
));
}
catch
(
Exception
$e
)
{
unset
(
$recurrence
[
$k
]);
}
}
}
}
else
{
$recurrence
=
''
;
}
return
$recurrence
;
}
/**
* Handler for user_delete plugin hook
*/
public
function
user_delete
(
$args
)
{
$db
=
$this
->
rc
->
db
;
$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
))
{
$list_ids
[]
=
$row
[
'tasklist_id'
];
}
if
(!
empty
(
$list_ids
))
{
foreach
(
array
(
$this
->
db_tasks
,
$this
->
db_lists
)
as
$table
)
{
$db
->
query
(
sprintf
(
"DELETE FROM $table WHERE tasklist_id IN (%s)"
,
join
(
','
,
$list_ids
)));
}
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Mon, Apr 6, 1:07 AM (2 d, 19 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
c8/44/eb5e0277b72d99e974443165dc26
Default Alt Text
tasklist_database_driver.php (26 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline