[%s]");
SDV($ReminderLogKeyword, 'Reminder');
SDV($ReminderIncludeSuffix, '');
SDVA($ReminderTable, array(
"W"=>120,
"H"=>120,
"M"=>1,
"B"=>2,
));
SDVA($ReminderSPat,
array("/^(\\*|[:]?{$ReminderLogKeyword}[:])\\s*(=|~)(w?\\d\\d?)(?:\\/(\\d\\d?))?(?:\\/(\\d{4}))?\\s/m"
=>'mu_remindernext' ));
function mu_remindernext($m) {
return ReminderNext($m[1].' '.$m[2], $m[3], $m[4], $m[5]);
}
SDV($RemindersLogs, array("\$SiteGroup.AllReminders"));
$MarkupExpr['remtoday'] = 'Keep(str_replace("\'", "'", FmtReminder($args[0],
"$args[0] today=$args[1] pastdays=0 futuredays=0 dayheaders=0 liststyle=0" ) ))';
function FmtToSec($f, $mtply=1) {
global $Now;
return intval(ltrim(PSFT($f, $Now), '0'))*$mtply;
}
function EasterJD($y) {
$western = gregoriantojd(3, 21, $y);
$eastern = juliantojd(3, 21, $y);
$wadd = easter_days($y, CAL_EASTER_ALWAYS_GREGORIAN);
$eadd = easter_days($y, CAL_EASTER_ALWAYS_JULIAN);
return array('W'=>$western+$wadd, 'E'=>$eastern+$eadd);
}
function NthWeekdayMonthYear($nth, $dow, $month, $year) {
if($nth>=1) {
$first = strtotime("$year-$month-01");
$fdow = date('w', $first);
$offset = ($dow - $fdow + 7) % 7;
$firstweekday = strtotime("+$offset days", $first);
}
else {
$last = strtotime("last day of $year-$month");
$ldow = date('w', $last);
$offset = ($ldow - $dow + 7) % 7;
$lastweekday = strtotime("-$offset days", $last);
}
if($nth == 1) $wday = $firstweekday;
elseif($nth == 0) $wday = $lastweekday;
elseif($nth>1) {
$wday = strtotime("+" . ($nth-1) . " weeks", $firstweekday);
}
elseif($nth<0) {
$wday = strtotime("$nth weeks", $lastweekday);
}
return PSFT('%m-%d', $wday);
}
function FmtReminder($pagename, $args, $content='') {
global $Now, $InputValues, $ReminderPastDays, $ReminderFutureDays, $ReminderTable, $ReminderFmt,
$ReminderLocale, $ReminderDayMonth, $ReminderDateFormat, $ReminderIncludeSuffix, $HTMLStylesFmt,
$EnableReminderRefresh, $EnableReminderEmptyDays, $SiteAllReminders, $QualifyPatterns, $HTMLHeaderFmt,
$ReminderWeeklyFix;
if($EnableReminderRefresh) {
$sec = 24*3600 - (FmtToSec('%H', 3600) + FmtToSec('%M', 60) + FmtToSec('%S'))+300;
$HTMLHeaderFmt['refresh-reminder'] = "";
}
$opt = ParseArgs($args);
$TH = IsEnabled($opt['th'], $ReminderTable["H"]);
$TW = IsEnabled($opt['tw'], $ReminderTable['W']);
$TM = IsEnabled($opt['tm'], $ReminderTable['M']);
$TB = IsEnabled($opt['tb'], $ReminderTable['B']);
$drur = "div.remtable ul.reminder";
$HTMLStylesFmt['remtable'] = "$drur { font-size: 90%; line-height: 1.1em; }
$drur li.date { position: relative; display: block; float: left; overflow: hidden;
height: {$TH}px; width: {$TW}px; border: {$TB}px solid #ddd; margin-left: {$TM}px; }
$drur li.date:hover { overflow: visible; z-index: 50;}
$drur li.today { border: {$TB}px solid #a00; font-size: inherit; }
$drur li.empty { border-color: #fff; background-color: #fff;}\n";
if(isset($opt['weeks'])) $HTMLStylesFmt['remtable'] .= "$drur li.w{$opt['weeks']} { clear: left;}\n";
$Tsptintf = "$drur li.w%d:first-child, $drur li.overdue + li.w%d {margin-left: %dpx;}\n";
for($i=1; $i<8; $i++) {
$j = $i%7;
$k = $i-1;
$margin = $k*($TW+2*$TB+$TM);
// $HTMLStylesFmt['remtable'] .= sprintf($Tsptintf, $j, $j, $margin);
}
$TodayNow = IsEnabled($opt['today'], PSFT('%Y-%m-%d', $Now));
$TodayNow2 = IsEnabled($opt['today'], PSFT('%Y%m%d', $Now));
if(! strpos($TodayNow, '-') ) $TodayNow = PSFT('%Y-%m-%d', strtotime($TodayNow) );
$dayheaders = IsEnabled($opt['dayheaders'], 1);
$liststyle = IsEnabled($opt['liststyle'], 1);
$expired = IsEnabled($opt['expired'], 1);
$pastdays = IsEnabled($opt['pastdays'], $ReminderPastDays);
$futuredays = IsEnabled($opt['futuredays'], $ReminderFutureDays);
$locale = IsEnabled($opt['locale'], $ReminderLocale);
$datefmt = IsEnabled($opt['datefmt'], $ReminderDateFormat);
$emptydays = (@$opt['emptydays']>'')? $opt['emptydays'] : $EnableReminderEmptyDays;
$df = explode('/', $ReminderDayMonth);
$onemonth = intval(IsEnabled($opt['onemonth'], @$_REQUEST['onemonth']));
$CurrentYear = intval(date('Y'));
$NextYear = $CurrentYear+1;
$easterdays = array();
for($i=0; $i<3; $i++) {
$easterdays[$i] = EasterJD($CurrentYear+$i);
}
$julianday = unixtojd();
if(@$opt[''][0]>'')$content .= "\n". IncludeText($pagename, $opt[''][0]);
if($locale)setlocale(LC_TIME, $locale);
$_DATES = array();
$lines = explode("\n", $content);
$out = "";
if($ReminderIncludeSuffix) {
$QP = array('/(REM)?$/m'=>'$1'.$ReminderIncludeSuffix) +$QualifyPatterns;
$QualifyPatterns = $QP;
}
$restart=1;
while($restart) {
$restart=0;
foreach($lines as $i=>$line)
if(preg_match("/^#include (.*?)$/", $line, $m)) {
array_splice($lines, count($lines), 0, explode("\n", IncludeText($pagename, PSS($m[1]))));
$lines[$i]='';
$restart=1;
}
}
if($ReminderIncludeSuffix) unset($QualifyPatterns['/(REM)?$/m']);
foreach($lines as $line) {
if(@$line[0]!='*') continue;
$line = preg_replace_callback('/\\{(\\*|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w[-\\w]*)\\}/', "MarkupPageVar", $line);
$line = preg_replace_callback('/\\{(\\(\\w+\\b.*?\\))\\}/', "MarkupMarkupExpression", $line);
@list($when, $what) = explode(' ', preg_replace("/^\\* */", '', $line), 2);
$md5 = md5($line);
$time = 1500; // 25*60
$iso = false;
$lwhat = strtolower($what);
preg_match('/\\b(?P[012]?\\d)[h:](?P[0-5]\\d)?(?: *(?P[ap])m)?\\b/i', $lwhat, $m);
if(!$m) preg_match('/\\b(?P[012]?\\d)(?P[ap])m\\b/i', $lwhat, $m);
if($m) {
$h = intval($m['hour']);
$time = 60*$h+intval(@$m['min']);
if(@$m['ampm']=='p' && $h<12) $time += 720;
elseif (@$m['ampm']=='a' && $h==12) $time -= 720;
}
# Weekly
if( preg_match('/^w(\\d+)$/i', $when, $m))
for($i=0; $isprintf($ReminderFmt, $what, $when, $md5), 'time'=>$time);
}
# Monthly
elseif(preg_match('/^(-?\\d+)$/i', $when, $m)&&$m[1]<32)
$_DATES["m".intval($m[1])][] =
array('what'=>sprintf($ReminderFmt, $what, $when, $md5), 'time'=>$time);
# Sticky
elseif( preg_match('/^(=|~)(\\d{4}-(\\d\\d-\\d\\d))$/i', $when, $iso)) {
if($iso[2]< $TodayNow && $iso[1] == '=' ) {
$_DATES['overdue'][] = sprintf($ReminderFmt, $what, $when, $md5);
}
else {
$_DATES[ $iso[3] ][] =
array('what'=>sprintf($ReminderFmt, $what, $when, $md5), 'time'=>$time);
}
}
# Yearly reminders
elseif(preg_match('/^(\\d+)\\/(\\d+)(?:\\/(\\d+))?$/i', $when, $m)
|| preg_match('/^(\\d{4})-?(\\d\\d)-?(\\d\\d)$/i', $when, $iso)) {
if(@$iso[0]) {
$x = array('m'=>intval($iso[2]), 'd'=>intval($iso[3]));
$m = array(3=>$iso[1]);
}
else
$x=array($df[0]=>intval($m[1]),$df[1]=>intval($m[2]));
$st = PSFT('%m-%d', strtotime("2000-{$x['m']}-{$x['d']}"));
$st2 = sprintf("%02d-%02d", $x['m'], $x['d']);
if($st!=$st2)
$_DATES['unknown'][] = sprintf($ReminderFmt, $what, $when, $md5);
else
$_DATES[ $st ][] =
array('y'=>@$m[3],'what'=>sprintf($ReminderFmt, $what, $when, $md5), 'time'=>$time);
}
# Start date, custom interval in days, weeks
elseif(preg_match('/^(\\d+)\\/(\\d+)\\/(\\d+)r(\\d+)([dw]?)$/i', $when, $n)) {
$m = array_map('intval', $n);
$x=array($df[0]=>$m[1], $df[1]=>$m[2], 'y'=>$m[3]);
$jdstart = unixtojd(strtotime("{$x['y']}-{$x['m']}-{$x['d']}"));
$rdays = $m[4];
if($n[5]=='w') $rdays*=7;
$_DATES[ 'custominterval' ][] = array(
'start'=>$jdstart,
'interval'=>$rdays,
'what'=>sprintf($ReminderFmt, $what, $when, $md5),
'time'=>$time);
}
# Multiple days DateStart..DateEnd
elseif(preg_match('/^(\\d{1,2})\\/(\\d{1,2})(?:\\/(\\d{4}))?\\.\\.(\\d{1,2})\\/(\\d{1,2})(?:\\/(\\d{4}))?(?:([mw])(\\d+))?$/i', $when, $m)) {
$x=array($df[0]=>intval($m[1]),$df[1]=>intval($m[2]));
$x2=array($df[0]=>intval($m[4]),$df[1]=>intval($m[5]));
$y2 = @$m[6]? $m[6] : date('Y');
$y1 = @$m[3]? $m[3] : $y2;
$T1 = strtotime("$y1-{$x['m']}-{$x['d']}");
$T2 = strtotime("$y2-{$x2['m']}-{$x2['d']}");
if($T1>$T2) {
if(@$m[6] || $x2['m']>2)
$T1 = strtotime( ($y2-1) ."-{$x['m']}-{$x['d']}");
else
$T2 = strtotime( ($y2+1) ."-{$x2['m']}-{$x2['d']}");
}
if( PSFT('%m-%d', $T1)!=sprintf("%02d-%02d", $x['m'], $x['d'])
|| PSFT('%m-%d', $T2)!=sprintf("%02d-%02d", $x2['m'], $x2['d'])) {
$_DATES['unknown'][] = "$what [$when] "
.PSFT('%m-%d', $T1).'!='.sprintf("%02d-%02d", $x['m'], $x['d'])
." "
.PSFT('%m-%d', $T2).'!='.sprintf("%02d-%02d", $x2['m'], $x2['d']);
continue;
}
if(@$m[6] && PSFT('%Y-%m-%d', $T2)< $TodayNow) {
$_DATES['overdue'][] = sprintf($ReminderFmt, $what, $when, $md5);
continue;
}
$T0 = 0;
$interval = @$m[7];
if($interval) {
$intdate = intval($m[8]);
$intday = [];
for($i=0;$isprintf($ReminderFmt, $what, $when, $md5), 'time'=>$Mtime);
continue;
}
if($interval == 'm') {
if(intval(PSFT('%d', $T0)) == $intdate)
$_DATES[ "m$st" ][] =
array('what'=>sprintf($ReminderFmt, $what, $when, $md5), 'time'=>$Mtime);
continue;
}
$_DATES[ "M$st" ][] =
array('what'=>sprintf($ReminderFmt, $what, $when, $md5), 'time'=>$Mtime);
}
}
# Easter
elseif(preg_match('/^([WE])E([-+]\\d+)([dw]?)$/', $when, $m)) {
$days = intval($m[2]);
if($m[3]=='w') $days *= 7;
for($i=0; $isprintf($ReminderFmt, $what, $when, $md5),
'time'=>$time,
'year'=>$CurrentYear+$i
);
}
}
# Nth Weekday of Month 4w4@11 Thanksgiving
elseif(preg_match('/^(-?[012345])w([0-7])@(0?[1-9]|1[012])$/', $when, $m)) {
$n = array_map('intval', $m);
$dow = ($n[2]+7-$ReminderWeeklyFix)%7;
for($i=0; $i<3; $i++) {
$st = NthWeekdayMonthYear($n[1], $dow, $n[3], $CurrentYear+$i);
$_DATES[$st][] = array(
'what'=>sprintf($ReminderFmt, $what, $when, $md5),
'time'=>$time,
'year'=>$CurrentYear+$i
);
}
}
else $_DATES['unknown'][] = sprintf($ReminderFmt, $what, $when, $md5);
}
if($expired && isset($_DATES['overdue']) && count($_DATES['overdue']) ) {
$out.="\n* %list reminder% %item date overdue% $[Expired]\n";
foreach($_DATES['overdue'] as $v)$out.="** $v\n";
}
if($onemonth && $onemonth<13) {
$y = $onemonth$jday) continue;
$jdiff = $jday - $a['start'];
if($jdiff % $a['interval'] === 0) {
$out["** %item custom% {$a['what']}\n"] = $a['time'];
}
}
}
if($out) {
asort($out);
$ret = implode('', array_keys($out));
}
if(!$liststyle) $ret = preg_replace("/%(list|item).*?%/", '', $ret);
if($ret>'' || $emptydays)
return ($dayheaders? "* %list reminder% %item date $class w$w%"
. PSFT($datefmt, $T). "\n":'') .$ret;
}
array_unshift($EditFunctions, "ReminderLogAll");
function ReminderLogAll($pagename,&$page,&$new) {
global $EnablePost, $RecentChangesFmt, $RemindersLogs, $ReminderSPat, $ReminderLogKeyword;
if (!$EnablePost) return;
$new['text'] = PPRA($ReminderSPat, $new['text']);
if (!@$RemindersLogs[0]) return;
$pslash = str_replace('.', '/', $pagename);
$pslashE = preg_quote("[[$pslash]]");
$oldmatch = preg_match("/^:?{$ReminderLogKeyword}:.*$/m", strval(@$page['text']));
$newmatch = preg_match_all("/^:?{$ReminderLogKeyword}:(.*)$/m", $new['text'], $m, PREG_PATTERN_ORDER);
if( $oldmatch || $newmatch ) {
foreach((array)$RemindersLogs as $p) {
$rcpage = ReadPage($p);
if($oldmatch)
$rcpage['text'] = preg_replace("!^\\*.* {$pslashE}\n!m", '', @$rcpage['text']);
if($newmatch)
foreach($m[1] as $v)
$rcpage['text'] .= "* ". trim($v). " . . [[$pslash]]\n";
WritePage($p, $rcpage);
}
}
}
function ReminderNext($prefix, $a, $b=0, $y=0) {
global $ReminderDayMonth, $Now;
if($a[0]=='w') {
$days = explode(' ', 'Sun Mon Tues Wednes Thurs Fri Satur');
$day = $days[ $a[1]%7 ];
return $prefix.PSFT("%Y-%m-%d", strtotime("{$day}day") )." ";
}
$df = explode('/', $ReminderDayMonth);
$x[$df[0]]=$a;
$x[$df[1]]=$b;
if($a && $b && $y)
return $prefix.PSFT("%Y-%m-%d", strtotime("$y-{$x['m']}-{$x['d']}") )." ";
if($b==0) {
$x['d'] = $a;
$x['m'] = 0;
}
$delta = "years";
if($x['m']==0){$delta = "months"; $x['m'] = date('n');}
if($y==0)$y =date('Y');
$Today = strtotime( PSFT("%Y-%m-%d"));
$Then = strtotime("$y-{$x['m']}-{$x['d']}");
for($i=0; $i<13; $i++) {
$Current = strtotime( "+$i $delta", $Then );
if($Today<=$Current)
return $prefix.PSFT("%Y-%m-%d", $Current)." ";
}
}