2010-01-24 20:12:30 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
This file is part of myTinyTodo.
|
2019-06-29 14:05:18 +00:00
|
|
|
(C) Copyright 2010-2011,2019 Max Pozdeev <maxpozdeev@gmail.com>
|
2014-01-28 12:38:06 +00:00
|
|
|
Licensed under the GNU GPL v2 license. See file COPYRIGHT for details.
|
2010-01-24 20:12:30 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//$dontStartSession = 1;
|
|
|
|
|
require_once('./init.php');
|
|
|
|
|
|
2010-11-10 18:33:01 +00:00
|
|
|
$onlyPublishedList = false;
|
|
|
|
|
if(!have_write_access()) $onlyPublishedList = true;
|
2010-01-24 20:12:30 +00:00
|
|
|
|
|
|
|
|
$listId = (int)_get('list');
|
2010-11-10 18:33:01 +00:00
|
|
|
$listData = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$listId ". ($onlyPublishedList ? "AND published=1" : "") );
|
2010-01-24 20:12:30 +00:00
|
|
|
if(!$listData) {
|
2010-11-10 18:33:01 +00:00
|
|
|
die("No such list or access denied");
|
2010-01-24 20:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$sqlSort = "ORDER BY compl ASC, ";
|
|
|
|
|
if($listData['sorting'] == 1) $sqlSort .= "prio DESC, ddn ASC, duedate ASC, ow ASC";
|
|
|
|
|
elseif($listData['sorting'] == 2) $sqlSort .= "ddn ASC, duedate ASC, prio DESC, ow ASC";
|
|
|
|
|
else $sqlSort .= "ow ASC";
|
|
|
|
|
|
|
|
|
|
$data = array();
|
|
|
|
|
$q = $db->dq("SELECT *, duedate IS NULL AS ddn FROM {$db->prefix}todolist WHERE list_id=$listId $sqlSort");
|
2020-10-14 18:20:44 +00:00
|
|
|
while($r = $q->fetch_assoc($q))
|
2010-01-24 20:12:30 +00:00
|
|
|
{
|
2020-10-14 18:20:44 +00:00
|
|
|
$data[] = $r;
|
2010-01-24 20:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
2011-01-07 11:32:04 +00:00
|
|
|
$format = _get('format');
|
2020-10-14 18:20:44 +00:00
|
|
|
|
2011-01-07 19:25:08 +00:00
|
|
|
if($format == 'ical') printICal($listData, $data);
|
2011-01-07 11:32:04 +00:00
|
|
|
else printCSV($listData, $data);
|
2010-01-24 20:12:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
function have_write_access()
|
|
|
|
|
{
|
|
|
|
|
if(is_logged()) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function printCSV($listData, $data)
|
|
|
|
|
{
|
2019-06-29 14:05:18 +00:00
|
|
|
$s = "\xEF\xBB\xBF". "Completed;Priority;Task;Notes;Tags;Due;DateCreated;DateCompleted\n";
|
2010-01-24 20:12:30 +00:00
|
|
|
foreach($data as $r)
|
|
|
|
|
{
|
2019-06-29 14:05:18 +00:00
|
|
|
$s .= ($r['compl']?'1':'0'). ';'.
|
|
|
|
|
$r['prio']. ';'. escape_csv($r['title']). ';'.
|
|
|
|
|
escape_csv($r['note']). ';'.
|
|
|
|
|
escape_csv($r['tags']). ';'.
|
|
|
|
|
$r['duedate']. ';'.
|
|
|
|
|
date('Y-m-d H:i:s O',$r['d_created']). ';'.
|
|
|
|
|
($r['d_completed'] ? date('Y-m-d H:i:s O',$r['d_completed']) :''). "\n";
|
2010-01-24 20:12:30 +00:00
|
|
|
}
|
2011-01-07 11:32:04 +00:00
|
|
|
header('Content-type: text/csv; charset=utf-8');
|
2020-09-12 14:02:15 +00:00
|
|
|
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.csv');
|
2010-01-24 20:12:30 +00:00
|
|
|
print $s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function escape_csv($v)
|
|
|
|
|
{
|
2019-06-29 14:08:41 +00:00
|
|
|
//escape formulas
|
|
|
|
|
$nf = '';
|
2019-06-29 17:19:40 +00:00
|
|
|
$trimmed = ltrim($v);
|
|
|
|
|
if (strlen($trimmed) > 0 && in_array(substr($trimmed, 0, 1), array('=', '+', '-', '@'))) {
|
2019-06-29 14:08:41 +00:00
|
|
|
$nf = "'";
|
|
|
|
|
}
|
|
|
|
|
return '"'. $nf. str_replace('"', '""', $v). '"';
|
2010-01-24 20:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
2011-01-07 11:32:04 +00:00
|
|
|
function printICal($listData, $data)
|
|
|
|
|
{
|
|
|
|
|
$mttToIcalPrio = array("1" => 5, "2" => 1);
|
|
|
|
|
$s = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nMETHOD:PUBLISH\r\nCALSCALE:GREGORIAN\r\nPRODID:-//myTinyTodo//iCalendar Export v1.4//EN\r\n".
|
|
|
|
|
"X-WR-CALNAME:". $listData['name']. "\r\nX-MTT-TIMEZONE:".Config::get('timezone')."\r\n";
|
|
|
|
|
# to-do
|
|
|
|
|
foreach($data as $r)
|
|
|
|
|
{
|
|
|
|
|
$a = array();
|
|
|
|
|
$a[] = "BEGIN:VTODO";
|
|
|
|
|
$a[] = "UID:". $r['uuid'];
|
|
|
|
|
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
|
|
|
|
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
|
|
|
|
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
|
|
|
|
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
|
|
|
|
if($r['duedate']) {
|
|
|
|
|
$dda = explode('-', $r['duedate']);
|
|
|
|
|
$a[] = "DUE;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
|
|
|
|
}
|
|
|
|
|
# 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'];
|
2020-10-14 18:20:44 +00:00
|
|
|
|
2011-01-07 11:32:04 +00:00
|
|
|
$descr = array();
|
|
|
|
|
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
|
|
|
|
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
|
|
|
|
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
|
|
|
|
|
|
|
|
|
if($r['compl']) {
|
|
|
|
|
$a[] = "STATUS:COMPLETED"; #used in Sunbird
|
|
|
|
|
$a[] = "COMPLETED:". gmdate('Ymd\THis\Z', $r['d_completed']);
|
|
|
|
|
#$a[] = "PERCENT-COMPLETE:100"; #used in Sunbird
|
|
|
|
|
}
|
|
|
|
|
if($r['tags'] != '') $a[] = utf8chunks("X-MTT-TAGS:". $r['tags']);
|
|
|
|
|
$a[] = "END:VTODO\r\n";
|
|
|
|
|
$s .= implode("\r\n", $a);
|
|
|
|
|
}
|
|
|
|
|
# events
|
|
|
|
|
foreach($data as $r)
|
|
|
|
|
{
|
2020-10-14 18:20:44 +00:00
|
|
|
if(!$r['duedate'] || $r['compl']) continue; # skip tasks completed and without duedate
|
2011-01-07 11:32:04 +00:00
|
|
|
$a = array();
|
|
|
|
|
$a[] = "BEGIN:VEVENT";
|
|
|
|
|
$a[] = "UID:_". $r['uuid']; # do not duplicate VTODO UID
|
|
|
|
|
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
|
|
|
|
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
|
|
|
|
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
|
|
|
|
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
|
|
|
|
if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']];
|
|
|
|
|
$dda = explode('-', $r['duedate']);
|
|
|
|
|
$a[] = "DTSTART;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
|
|
|
|
$a[] = "DTEND;VALUE=DATE:".date('Ymd', mktime(1,1,1,$dda[1],$dda[2],$dda[0]) + 86400);
|
|
|
|
|
$descr = array();
|
|
|
|
|
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
|
|
|
|
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
|
|
|
|
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
|
|
|
|
$a[] = "END:VEVENT\r\n";
|
|
|
|
|
$s .= implode("\r\n", $a);
|
|
|
|
|
}
|
|
|
|
|
$s .= "END:VCALENDAR\r\n";
|
|
|
|
|
header('Content-type: text/calendar; charset=utf-8');
|
2020-09-12 14:02:15 +00:00
|
|
|
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.ics');
|
2011-01-07 11:32:04 +00:00
|
|
|
print $s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function utf8chunks($text, $chunklen=75, $delimiter="\r\n\t")
|
|
|
|
|
{
|
|
|
|
|
if($text == '') return '';
|
|
|
|
|
preg_match_all('/./u', $text, $m);
|
|
|
|
|
$chars = $m[0];
|
|
|
|
|
$a = array();
|
|
|
|
|
$s = '';
|
|
|
|
|
$max = count($chars);
|
|
|
|
|
for($i=0; $i<$max; $i++)
|
|
|
|
|
{
|
|
|
|
|
$ch = $chars[$i];
|
|
|
|
|
if(strlen($s) + strlen($ch) > $chunklen) { # line should be not more than $chunklen bytes
|
|
|
|
|
$a[] = $s;
|
|
|
|
|
$s = $ch;
|
|
|
|
|
}
|
|
|
|
|
else $s .= $ch;
|
|
|
|
|
}
|
|
|
|
|
if($s != '') $a[] = $s;
|
|
|
|
|
return implode($delimiter, $a);
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-24 20:12:30 +00:00
|
|
|
?>
|