Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120840326
tasklist.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
16 KB
Referenced Files
None
Subscribers
None
tasklist.php
View Options
<?php
/**
* Tasks plugin for Roundcube webmail
*
* @version @package_version@
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2012, 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
extends
rcube_plugin
{
const
FILTER_MASK_TODAY
=
1
;
const
FILTER_MASK_TOMORROW
=
2
;
const
FILTER_MASK_WEEK
=
4
;
const
FILTER_MASK_LATER
=
8
;
const
FILTER_MASK_NODATE
=
16
;
const
FILTER_MASK_OVERDUE
=
32
;
const
FILTER_MASK_FLAGGED
=
64
;
const
FILTER_MASK_COMPLETE
=
128
;
public
static
$filter_masks
=
array
(
'today'
=>
self
::
FILTER_MASK_TODAY
,
'tomorrow'
=>
self
::
FILTER_MASK_TOMORROW
,
'week'
=>
self
::
FILTER_MASK_WEEK
,
'later'
=>
self
::
FILTER_MASK_LATER
,
'nodate'
=>
self
::
FILTER_MASK_NODATE
,
'overdue'
=>
self
::
FILTER_MASK_OVERDUE
,
'flagged'
=>
self
::
FILTER_MASK_FLAGGED
,
'complete'
=>
self
::
FILTER_MASK_COMPLETE
,
);
public
$task
=
'?(?!login|logout).*'
;
public
$rc
;
public
$driver
;
public
$timezone
;
public
$ui
;
public
$defaults
=
array
(
'date_format'
=>
"Y-m-d"
,
'time_format'
=>
"H:i"
,
'first_day'
=>
1
,
);
/**
* Plugin initialization.
*/
function
init
()
{
$this
->
rc
=
rcmail
::
get_instance
();
$this
->
register_task
(
'tasks'
,
'tasklist'
);
// load plugin configuration
$this
->
load_config
();
// load localizations
$this
->
add_texts
(
'localization/'
,
$this
->
rc
->
task
==
'tasks'
&&
(!
$this
->
rc
->
action
||
$this
->
rc
->
action
==
'print'
));
if
(
$this
->
rc
->
task
==
'tasks'
&&
$this
->
rc
->
action
!=
'save-pref'
)
{
$this
->
load_driver
();
// register calendar actions
$this
->
register_action
(
'index'
,
array
(
$this
,
'tasklist_view'
));
$this
->
register_action
(
'task'
,
array
(
$this
,
'task_action'
));
$this
->
register_action
(
'tasklist'
,
array
(
$this
,
'tasklist_action'
));
$this
->
register_action
(
'counts'
,
array
(
$this
,
'fetch_counts'
));
$this
->
register_action
(
'fetch'
,
array
(
$this
,
'fetch_tasks'
));
}
if
(!
$this
->
rc
->
output
->
ajax_call
&&
!
$this
->
rc
->
output
->
env
[
'framed'
])
{
require_once
(
$this
->
home
.
'/tasklist_ui.php'
);
$this
->
ui
=
new
tasklist_ui
(
$this
);
$this
->
ui
->
init
();
}
}
/**
* Helper method to load the backend driver according to local config
*/
private
function
load_driver
()
{
if
(
is_object
(
$this
->
driver
))
return
;
$driver_name
=
$this
->
rc
->
config
->
get
(
'tasklist_driver'
,
'database'
);
$driver_class
=
'tasklist_'
.
$driver_name
.
'_driver'
;
require_once
(
$this
->
home
.
'/drivers/tasklist_driver.php'
);
require_once
(
$this
->
home
.
'/drivers/'
.
$driver_name
.
'/'
.
$driver_class
.
'.php'
);
switch
(
$driver_name
)
{
case
"kolab"
:
$this
->
require_plugin
(
'libkolab'
);
default
:
$this
->
driver
=
new
$driver_class
(
$this
);
break
;
}
// get user's timezone
$this
->
timezone
=
new
DateTimeZone
(
$this
->
rc
->
config
->
get
(
'timezone'
,
'GMT'
));
}
/**
*
*/
public
function
task_action
()
{
$action
=
get_input_value
(
'action'
,
RCUBE_INPUT_GPC
);
$rec
=
get_input_value
(
't'
,
RCUBE_INPUT_POST
,
true
);
$oldrec
=
$rec
;
$success
=
$refresh
=
false
;
switch
(
$action
)
{
case
'new'
:
$oldrec
=
null
;
$rec
=
$this
->
prepare_task
(
$rec
);
$rec
[
'uid'
]
=
$this
->
generate_uid
();
$temp_id
=
$rec
[
'tempid'
];
if
(
$success
=
$this
->
driver
->
create_task
(
$rec
))
{
$refresh
=
$this
->
driver
->
get_task
(
$rec
);
if
(
$temp_id
)
$refresh
[
'tempid'
]
=
$temp_id
;
}
break
;
case
'edit'
:
$rec
=
$this
->
prepare_task
(
$rec
);
if
(
$success
=
$this
->
driver
->
edit_task
(
$rec
))
$refresh
=
$this
->
driver
->
get_task
(
$rec
);
break
;
case
'delete'
:
if
(!(
$success
=
$this
->
driver
->
delete_task
(
$rec
,
false
)))
$this
->
rc
->
output
->
command
(
'plugin.reload_data'
);
break
;
case
'undelete'
:
if
(
$success
=
$this
->
driver
->
undelete_task
(
$rec
))
$refresh
=
$this
->
driver
->
get_task
(
$rec
);
break
;
}
if
(
$success
)
{
$this
->
rc
->
output
->
show_message
(
'successfullysaved'
,
'confirmation'
);
$this
->
update_counts
(
$oldrec
,
$refresh
);
}
else
$this
->
rc
->
output
->
show_message
(
'tasklist.errorsaving'
,
'error'
);
// unlock client
$this
->
rc
->
output
->
command
(
'plugin.unlock_saving'
);
if
(
$refresh
)
{
$this
->
encode_task
(
$refresh
);
$this
->
rc
->
output
->
command
(
'plugin.refresh_task'
,
$refresh
);
}
}
/**
* repares new/edited task properties before save
*/
private
function
prepare_task
(
$rec
)
{
// try to be smart and extract date from raw input
if
(
$rec
[
'raw'
])
{
foreach
(
array
(
'today'
,
'tomorrow'
,
'sunday'
,
'monday'
,
'tuesday'
,
'wednesday'
,
'thursday'
,
'friday'
,
'saturday'
,
'sun'
,
'mon'
,
'tue'
,
'wed'
,
'thu'
,
'fri'
,
'sat'
)
as
$word
)
{
$locwords
[]
=
'/^'
.
preg_quote
(
mb_strtolower
(
$this
->
gettext
(
$word
)))
.
'
\b
/i'
;
$normwords
[]
=
$word
;
$datewords
[]
=
$word
;
}
foreach
(
array
(
'jan'
,
'feb'
,
'mar'
,
'apr'
,
'may'
,
'jun'
,
'jul'
,
'aug'
,
'sep'
,
'oct'
,
'now'
,
'dec'
)
as
$month
)
{
$locwords
[]
=
'/('
.
preg_quote
(
mb_strtolower
(
$this
->
gettext
(
'long'
.
$month
)))
.
'|'
.
preg_quote
(
mb_strtolower
(
$this
->
gettext
(
$month
)))
.
')
\b
/i'
;
$normwords
[]
=
$month
;
$datewords
[]
=
$month
;
}
foreach
(
array
(
'on'
,
'this'
,
'next'
,
'at'
)
as
$word
)
{
$fillwords
[]
=
preg_quote
(
mb_strtolower
(
$this
->
gettext
(
$word
)));
$fillwords
[]
=
$word
;
}
$raw
=
trim
(
$rec
[
'raw'
]);
$date_str
=
''
;
// translate localized keywords
$raw
=
preg_replace
(
'/^('
.
join
(
'|'
,
$fillwords
)
.
')
\s
*/i'
,
''
,
$raw
);
$raw
=
preg_replace
(
$locwords
,
$normwords
,
$raw
);
// find date pattern
$date_pattern
=
'!^(
\d
+[./-]
\s
*)?((?:
\d
+[./-])|'
.
join
(
'|'
,
$datewords
)
.
')
\.
?(
\s
+
\d
{4})?[:;,]?
\s
+!i'
;
if
(
preg_match
(
$date_pattern
,
$raw
,
$m
))
{
$date_str
.=
$m
[
1
]
.
$m
[
2
]
.
$m
[
3
];
$raw
=
preg_replace
(
array
(
$date_pattern
,
'/^('
.
join
(
'|'
,
$fillwords
)
.
')
\s
*/i'
),
''
,
$raw
);
// add year to date string
if
(
$m
[
1
]
&&
!
$m
[
3
])
$date_str
.=
date
(
'Y'
);
}
// find time pattern
$time_pattern
=
'/^(
\d
+([:.]
\d
+)?(
\s
*[hapm.]+)?),?
\s
+/i'
;
if
(
preg_match
(
$time_pattern
,
$raw
,
$m
))
{
$has_time
=
true
;
$date_str
.=
(
$date_str
?
' '
:
'today '
)
.
$m
[
1
];
$raw
=
preg_replace
(
$time_pattern
,
''
,
$raw
);
}
// yes, raw input matched a (valid) date
if
(
strlen
(
$date_str
)
&&
strtotime
(
$date_str
)
&&
(
$date
=
new
DateTime
(
$date_str
,
$this
->
timezone
)))
{
$rec
[
'date'
]
=
$date
->
format
(
'Y-m-d'
);
if
(
$has_time
)
$rec
[
'time'
]
=
$date
->
format
(
'H:i'
);
$rec
[
'title'
]
=
$raw
;
}
else
$rec
[
'title'
]
=
$rec
[
'raw'
];
}
// normalize input from client
if
(
isset
(
$rec
[
'complete'
]))
{
$rec
[
'complete'
]
=
floatval
(
$rec
[
'complete'
]);
if
(
$rec
[
'complete'
]
>
1
)
$rec
[
'complete'
]
/=
100
;
}
if
(
isset
(
$rec
[
'flagged'
]))
$rec
[
'flagged'
]
=
intval
(
$rec
[
'flagged'
]);
// fix for garbage input
if
(
$rec
[
'description'
]
==
'null'
)
$rec
[
'description'
]
=
''
;
foreach
(
$rec
as
$key
=>
$val
)
{
if
(
$val
==
'null'
)
$rec
[
$key
]
=
null
;
}
if
(!
empty
(
$rec
[
'date'
]))
{
try
{
$date
=
new
DateTime
(
$rec
[
'date'
]
.
' '
.
$rec
[
'time'
],
$this
->
timezone
);
$rec
[
'date'
]
=
$date
->
format
(
'Y-m-d'
);
if
(!
empty
(
$rec
[
'time'
]))
$rec
[
'time'
]
=
$date
->
format
(
'H:i'
);
}
catch
(
Exception
$e
)
{
$rec
[
'date'
]
=
$rec
[
'time'
]
=
null
;
}
}
return
$rec
;
}
/**
*
*/
public
function
tasklist_action
()
{
$action
=
get_input_value
(
'action'
,
RCUBE_INPUT_GPC
);
$list
=
get_input_value
(
'l'
,
RCUBE_INPUT_POST
,
true
);
$success
=
false
;
if
(
isset
(
$list
[
'showalarms'
]))
$list
[
'showalarms'
]
=
intval
(
$list
[
'showalarms'
]);
switch
(
$action
)
{
case
'new'
:
$list
+=
array
(
'showalarms'
=>
true
,
'active'
=>
true
);
if
(
$insert_id
=
$this
->
driver
->
create_list
(
$list
))
{
$list
[
'id'
]
=
$insert_id
;
$this
->
rc
->
output
->
command
(
'plugin.insert_tasklist'
,
$list
);
$success
=
true
;
}
break
;
case
'edit'
:
if
(
$newid
=
$this
->
driver
->
edit_list
(
$list
))
{
$list
[
'oldid'
]
=
$list
[
'id'
];
$list
[
'id'
]
=
$newid
;
$this
->
rc
->
output
->
command
(
'plugin.update_tasklist'
,
$list
);
$success
=
true
;
}
break
;
case
'subscribe'
:
$success
=
$this
->
driver
->
subscribe_list
(
$list
);
break
;
}
if
(
$success
)
$this
->
rc
->
output
->
show_message
(
'successfullysaved'
,
'confirmation'
);
else
$this
->
rc
->
output
->
show_message
(
'tasklist.errorsaving'
,
'error'
);
$this
->
rc
->
output
->
command
(
'plugin.unlock_saving'
);
}
/**
*
*/
public
function
fetch_counts
()
{
$lists
=
null
;
$counts
=
$this
->
driver
->
count_tasks
(
$lists
);
$this
->
rc
->
output
->
command
(
'plugin.update_counts'
,
$counts
);
}
/**
* Adjust the cached counts after changing a task
*
*
*/
public
function
update_counts
(
$oldrec
,
$newrec
)
{
// rebuild counts until this function is finally implemented
$this
->
fetch_counts
();
// $this->rc->output->command('plugin.update_counts', $counts);
}
/**
*
*/
public
function
fetch_tasks
()
{
$f
=
intval
(
get_input_value
(
'filter'
,
RCUBE_INPUT_GPC
));
$search
=
get_input_value
(
'q'
,
RCUBE_INPUT_GPC
);
$filter
=
array
(
'mask'
=>
$f
,
'search'
=>
$search
);
$lists
=
get_input_value
(
'lists'
,
RCUBE_INPUT_GPC
);;
// convert magic date filters into a real date range
switch
(
$f
)
{
case
self
::
FILTER_MASK_TODAY
:
$today
=
new
DateTime
(
'now'
,
$this
->
timezone
);
$filter
[
'from'
]
=
$filter
[
'to'
]
=
$today
->
format
(
'Y-m-d'
);
break
;
case
self
::
FILTER_MASK_TOMORROW
:
$tomorrow
=
new
DateTime
(
'now + 1 day'
,
$this
->
timezone
);
$filter
[
'from'
]
=
$filter
[
'to'
]
=
$tomorrow
->
format
(
'Y-m-d'
);
break
;
case
self
::
FILTER_MASK_OVERDUE
:
$yesterday
=
new
DateTime
(
'yesterday'
,
$this
->
timezone
);
$filter
[
'to'
]
=
$yesterday
->
format
(
'Y-m-d'
);
break
;
case
self
::
FILTER_MASK_WEEK
:
$today
=
new
DateTime
(
'now'
,
$this
->
timezone
);
$filter
[
'from'
]
=
$today
->
format
(
'Y-m-d'
);
$weekend
=
new
DateTime
(
'now + 7 days'
,
$this
->
timezone
);
$filter
[
'to'
]
=
$weekend
->
format
(
'Y-m-d'
);
break
;
case
self
::
FILTER_MASK_LATER
:
$date
=
new
DateTime
(
'now + 8 days'
,
$this
->
timezone
);
$filter
[
'from'
]
=
$date
->
format
(
'Y-m-d'
);
break
;
}
$data
=
$this
->
task_tree
=
$this
->
task_titles
=
array
();
foreach
(
$this
->
driver
->
list_tasks
(
$filter
,
$lists
)
as
$rec
)
{
if
(
$rec
[
'parent_id'
])
{
$this
->
task_tree
[
$rec
[
'id'
]]
=
$rec
[
'parent_id'
];
}
$this
->
encode_task
(
$rec
);
// apply filter; don't trust the driver on this :-)
if
((!
$f
&&
$rec
[
'complete'
]
<
1.0
)
||
(
$rec
[
'mask'
]
&
$f
))
$data
[]
=
$rec
;
}
// sort tasks according to their hierarchy level and due date
usort
(
$data
,
array
(
$this
,
'task_sort_cmp'
));
$this
->
rc
->
output
->
command
(
'plugin.data_ready'
,
$data
);
}
/**
* Prepare the given task record before sending it to the client
*/
private
function
encode_task
(&
$rec
)
{
$rec
[
'mask'
]
=
$this
->
filter_mask
(
$rec
);
$rec
[
'flagged'
]
=
intval
(
$rec
[
'flagged'
]);
$rec
[
'complete'
]
=
floatval
(
$rec
[
'complete'
]);
if
(
$rec
[
'date'
])
{
try
{
$date
=
new
DateTime
(
$rec
[
'date'
]
.
' '
.
$rec
[
'time'
],
$this
->
timezone
);
$rec
[
'datetime'
]
=
intval
(
$date
->
format
(
'U'
));
$rec
[
'date'
]
=
$date
->
format
(
$this
->
rc
->
config
->
get
(
'date_format'
,
'Y-m-d'
));
$rec
[
'_hasdate'
]
=
1
;
}
catch
(
Exception
$e
)
{
$rec
[
'date'
]
=
$rec
[
'datetime'
]
=
null
;
}
}
else
{
$rec
[
'date'
]
=
$rec
[
'datetime'
]
=
null
;
$rec
[
'_hasdate'
]
=
0
;
}
if
(!
isset
(
$rec
[
'_depth'
]))
{
$rec
[
'_depth'
]
=
0
;
$parent_id
=
$this
->
task_tree
[
$rec
[
'id'
]];
while
(
$parent_id
)
{
$rec
[
'_depth'
]++;
$rec
[
'parent_title'
]
=
$this
->
task_titles
[
$parent_id
];
$parent_id
=
$this
->
task_tree
[
$parent_id
];
}
}
$this
->
task_titles
[
$rec
[
'id'
]]
=
$rec
[
'title'
];
}
/**
* Compare function for task list sorting.
* Nested tasks need to be sorted to the end.
*/
private
function
task_sort_cmp
(
$a
,
$b
)
{
$d
=
$a
[
'_depth'
]
-
$b
[
'_depth'
];
if
(!
$d
)
$d
=
$b
[
'_hasdate'
]
-
$a
[
'_hasdate'
];
if
(!
$d
)
$d
=
$a
[
'datetime'
]
-
$b
[
'datetime'
];
return
$d
;
}
/**
* Compute the filter mask of the given task
*
* @param array Hash array with Task record properties
* @return int Filter mask
*/
public
function
filter_mask
(
$rec
)
{
static
$today
,
$tomorrow
,
$weeklimit
;
if
(!
$today
)
{
$today_date
=
new
DateTime
(
'now'
,
$this
->
timezone
);
$today
=
$today_date
->
format
(
'Y-m-d'
);
$tomorrow_date
=
new
DateTime
(
'now + 1 day'
,
$this
->
timezone
);
$tomorrow
=
$tomorrow_date
->
format
(
'Y-m-d'
);
$week_date
=
new
DateTime
(
'now + 7 days'
,
$this
->
timezone
);
$weeklimit
=
$week_date
->
format
(
'Y-m-d'
);
}
$mask
=
0
;
if
(
$rec
[
'flagged'
])
$mask
|=
self
::
FILTER_MASK_FLAGGED
;
if
(
$rec
[
'complete'
]
==
1.0
)
$mask
|=
self
::
FILTER_MASK_COMPLETE
;
if
(
empty
(
$rec
[
'date'
]))
$mask
|=
self
::
FILTER_MASK_NODATE
;
else
if
(
$rec
[
'date'
]
==
$today
)
$mask
|=
self
::
FILTER_MASK_TODAY
;
else
if
(
$rec
[
'date'
]
==
$tomorrow
)
$mask
|=
self
::
FILTER_MASK_TOMORROW
;
else
if
(
$rec
[
'date'
]
<
$today
)
$mask
|=
self
::
FILTER_MASK_OVERDUE
;
else
if
(
$rec
[
'date'
]
>
$tomorrow
&&
$rec
[
'date'
]
<=
$weeklimit
)
$mask
|=
self
::
FILTER_MASK_LATER
;
else
if
(
$rec
[
'date'
]
>
$weeklimit
)
$mask
|=
self
::
FILTER_MASK_LATER
;
return
$mask
;
}
/******* UI functions ********/
/**
* Render main view of the tasklist task
*/
public
function
tasklist_view
()
{
$this
->
ui
->
init
();
$this
->
ui
->
init_templates
();
$this
->
rc
->
output
->
set_pagetitle
(
$this
->
gettext
(
'navtitle'
));
$this
->
rc
->
output
->
send
(
'tasklist.mainview'
);
}
/******* Utility functions *******/
/**
* Generate a unique identifier for an event
*/
public
function
generate_uid
()
{
return
strtoupper
(
md5
(
time
()
.
uniqid
(
rand
()))
.
'-'
.
substr
(
md5
(
$this
->
rc
->
user
->
get_username
()),
0
,
16
));
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Apr 24, 2:25 PM (1 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
c1/dd/156ded83ef78120ab869181cadce
Default Alt Text
tasklist.php (16 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline