// Based heavily on mdp_calendar - thanks!
//TODO: Investigate
/*
$d = new DateTime('2008-12-22 12:52');
echo $d->getTimezone()->getName();
*/
if( $date = gps('date') ) {
$_GET['month'] = $date;
}
function smd_calendar($atts, $thing='') {
global $pretext, $variable, $prefs, $smd_cal_flag, $sdm_cal_ucls, $smd_cal_id, $smd_year, $smd_month, $smd_week, $smd_day;
extract(lAtts(array(
'time' => 'any', // past, future, any
'size' => 'large', // small or large (calendar)
'expired' => '', // 0=no, 1=yes publish expired events, empty=use prefs
'category' => '',
'section' => '',
'author' => '',
'status' => 'live',
'static' => '',
'form' => '',
'spanform' => 'SMD_SAME',
'recurform' => 'SMD_SAME',
'cellform' => '',
'stepfield' => '',
'skipfield' => '',
'showskipped' => '0',
'showspanned' => '1',
'holidays' => '',
'holidayflags' => 'standard', // permit these events to "land" on a holiday (standard, recur, multi)
'classlevels' => 'cell, event', // cell, event, cellplus (combines event and cell into cell level classes)
'linkposted' => 'recur, multi, multiprev, multilast', // which events cause the minical to link to posted date
'classprefixes' => 'smd_cal_, smd_cal_ev_', // 1st=cell-level pfx, 2nd=event-level pfx (optional)
'class' => '', // Table class
'rowclass' => '',
'cellclass' => '',
'emptyclass' => 'empty',
'isoweekclass' => 'week',
'navclass' => 'navprev, navnext',
'navarrow' => '<, >',
'navid' => '',
'eventclasses' => 'category',
'eventwraptag' => 'span',
'select' => '', // week, month and/or year (to display dropdowns)
'selectbtn' => '', // empty = autoselect (onchange), or text to go on the submit button
'myclass' => '', // month-year header class
'mywraptag' => '', // month-year header wraptag
'id' => '', // Table ID (=calid)
'week' => '',
'month' => '',
'year' => '',
'yearwidth' => '0,0', // number of years either side of the first/last article to permit
'isoweeks' => '', // empty = don't show ISO weeks; or text of column heading, text of cell prefix
'dayformat' => 'ABBR', // ABBR = %a, FULL = %A, or custom strftime string
'monthformat' => 'FULL', // ABBR = %b, FULL = %B, or custom strftime string
'firstday' => 0, // 1st day of week 0=Sunday, 6=Saturday (forced to Monday if isoweeks=1)
'maintain' => 'calid', // when navigating, keep these items in the URL
'gmt' => 0,
'lang' => '',
'debug' => 0,
), $atts));
$future = ( $time != 'past' ) ? true : false; // Determine heading style
$status = ($status) ? $status : 'live'; // in case status has been emptied
$firstday = ($isoweeks == '') ? $firstday : 1;
$spanform = ($spanform == 'SMD_SAME') ? $form : $spanform;
$recurform = ($recurform == 'SMD_SAME') ? $form : $recurform;
$cellform = (empty($cellform)) ? '' : fetch_form($cellform);
// Set up the class prefixes
$clevs = do_list($classlevels);
$cls = do_list($classprefixes);
$classprefix = $evclassprefix = $cls[0];
if (count($cls) > 1){
$evclassprefix = $cls[1];
}
// Set up the nav class(es)
$maintain = do_list($maintain);
$navarrow = do_list($navarrow);
$navparr = $navarrow[0];
$navnarr = (count($navarrow) > 1) ? $navarrow[1] : $navarrow[0];
$navclass = do_list($navclass);
$navpclass = $navclass[0];
$navnclass = (count($navclass) > 1) ? $navclass[1] : $navclass[0];
// Filters
$fopts = array();
$catSQL = $secSQL = $authSQL = '';
if($category) {
$fopts['c'] = $category;
$catSQL = doQuote(join("','", doSlash(do_list($category))));
$catSQL = " AND ( Category1 IN (".$catSQL.") OR Category2 IN (".$catSQL.") ) ";
}
if($section) {
$fopts['s'] = $section;
$secSQL = doQuote(join("','", doSlash(do_list($section))));
$secSQL = " AND Section IN (".$secSQL.") ";
}
if($author) {
$fopts['author'] = htmlentities(gps('author'));
$authSQL = doQuote(join("','", doSlash(do_list($author))));
$authSQL = " AND AuthorID IN (".$authSQL.") ";
}
$status = do_list($status);
$stati = array();
foreach ($status as $stat) {
if (empty($stat)) {
continue;
} else if (is_numeric($stat)) {
$stati[] = $stat;
} else {
$stati[] = getStatusNum($stat);
}
}
$stati = " Status IN (".doQuote(join(',', $stati)).")";
$expired = ($expired) ? $expired : $prefs['publish_expired_articles'];
$expired = (($expired) ? '' : ' AND (now() <= Expires OR Expires = '.NULLDATETIME.')');
$eventclasses = do_list($eventclasses);
$holidayflags = do_list($holidayflags);
$linkposted = do_list($linkposted);
// Work out the first and last posts to determine the year range
$earliest = safe_row('unix_timestamp(Posted) AS uPosted', 'textpattern', $stati.(($category) ? $catSQL : '').(($section) ? $secSQL : '').(($author) ? $authSQL : '').' ORDER BY Posted ASC LIMIT 0, 1', $debug);
$latest = safe_row('unix_timestamp(LastMod) AS uLastMod', 'textpattern', $stati.(($category) ? $catSQL : '').(($section) ? $secSQL : '').(($author) ? $authSQL : '').' AND Posted < now() ORDER BY LastMod DESC LIMIT 0, 1', $debug);
$yearwidth = do_list($yearwidth);
if (count($yearwidth) == 1) $yearwidth[1] = $yearwidth[0];
$earliest = date("Y", strtotime("-".$yearwidth[0]." year", ( (empty($earliest)) ? time() : $earliest['uPosted']) ) );
$latest = date("Y", strtotime("+".$yearwidth[1]." year", ( (empty($latest)) ? time() : $latest['uLastMod']) ) );
// Check the URL for current date and calendar target info
$incoming_calid = gps('calid');
$incoming_year = (gps('y') and is_numeric(gps('y'))) ? (int)gps('y') : '';
$incoming_month = (gps('m') and is_numeric(gps('m'))) ? (int)gps('m') : '';
$incoming_week = (gps('w') and is_numeric(gps('w'))) ? (int)gps('w') : '';
if($static) { // if we're static w/o any supplied vars, use the current date
if(!$year) { $year = safe_strftime('%Y'); }
if(!$month) { $month = safe_strftime('%m'); }
} else { // otherwise use current date only if there's nothing else
if( $id == $incoming_calid ) { // use incoming
$year = ($incoming_year) ? $incoming_year : (($year) ? $year : safe_strftime('%Y'));
$month = ($incoming_month) ? $incoming_month : (($month) ? $month : safe_strftime('%m'));
// If week is used, adjust month so it encompasses the given week
$week = $incoming_week;
if ($week) {
$month = safe_strftime("%m", gmmktime (1,1,1,1,7*$week,$year)); // Guess the month from the week
}
} else { // use current
if(!$year) { $year = safe_strftime('%Y'); }
if(!$month) { $month = safe_strftime('%m'); }
if($week) { $month = safe_strftime("%m", gmmktime (1,1,1,1,7*$week,$year)); }
}
}
$smd_cal_id = ($incoming_calid) ? $incoming_calid : $id;
$smd_year = $year; $smd_month = $month; // $smd_week and smd_day are set per event later
// The times in the DB are stored using the server's local time, so we don't
// want to adjust anything (since mktime uses the server's local time).
//TODO: Worry about gmt / dst
$ts_first = mktime(0, 0, 0, $month, 1, $year);
$ts_last = mktime(23, 59, 59, $month, date('t',$ts_first), $year);
$extrasql = $catSQL . $secSQL . $authSQL;
switch($time) {
case "any" : break;
case "future" : $extrasql .= " AND Posted > CURDATE()"; break;
default : $extrasql .= " AND Posted < CURDATE()"; break; // The past
}
// Holidays are global 'exclusions', either defined directly or in a
$holidays = do_list($holidays);
$txphols = do_list($holidays[0], ":");
if ($txphols[0] == "txpvar") {
$holidays = do_list($variable[$txphols[1]]);
}
// Force each holiday to a known format. Holidays without years use current year
foreach ($holidays as $key => $val) {
if (empty($val)) continue;
$numparts = preg_match('/^([\d\w]+).?([\d\w]+).?([\d\w]+)?$/', $val, $parts);
if ($numparts) {
if (count($parts) == 3) {
$parts[3] = $year;
}
$val = str_pad($parts[1], 2, '0', STR_PAD_LEFT).'-'.str_pad($parts[2], 2, '0', STR_PAD_LEFT).'-'.$parts[3];
}
$holidays[$key] = date("d-M-Y", strtotime($val));
}
if ($debug > 0 && !empty($holidays) && $holidays[0] != '') {
echo "++ HOLIDAYS ++ ";
dmp($holidays);
}
// Get all matching articles in (and before) this month
$events = array();
$sql2 = $stati . " HAVING uPosted <= ".$ts_last . $expired . $extrasql ." ORDER BY Posted ASC";
$grabCols = '*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires';
$evlist = safe_rows($grabCols, 'textpattern', $sql2, $debug);
article_push();
// If any events recur and fall within the current month, add those as well
// If any dates are to be excluded, the entry is skipped UNLESS showskipped indicates otherwise
foreach ($evlist as $row) {
$idx = 0; // In case the 1st day of the month is a continuation of an event from the end of the previous month
$start = $row['uPosted'];
$start_date = date("Y-m-d", $start); // For recurring/spanned events on a minical, this is the event the cell links to
$real_end = $row['uExpires'];
$end = ($real_end != 0 && $real_end < $ts_last) ? $real_end : $ts_last;
$smd_cal_flag = $smd_cal_ucls = array();
if ($debug > 1) {
echo '++ EVENT START // END // REAL END ++';
dmp($row['Title']);
dmp(date('d-M-Y H:i:s', $start) .' // '. date('d-M-Y H:i:s', $end) .' // '. date('d-M-Y H:i:s', $real_end));
if ($debug > 2) {
dmp($row);
}
}
$multi = ($row['uExpires'] > $row['uPosted'] && $row['uExpires'] > $ts_first) ? true : false;
$recur = (empty($row[$stepfield])) ? false : true;
$hol_hit = in_array(date("d-M-Y", $start), $holidays);
$evclasses = array();
foreach ($eventclasses as $evcls) {
switch ($evcls) {
case "":
break;
case "gcat":
if (isset($pretext['c']) && !empty($pretext['c'])) {
$evclasses[] = $evclassprefix.$pretext['c'];
}
break;
case "category":
if (isset($row['Category1']) && !empty($row['Category1'])) {
$evclasses[] = $evclassprefix.$row['Category1'];
}
if (isset($row['Category2']) && !empty($row['Category2'])) {
$evclasses[] = $evclassprefix.$row['Category2'];
}
break;
case "section":
if (isset($pretext['s']) && !empty($pretext['s'])) {
$evclasses[] = $evclassprefix.$pretext['s'];
}
break;
case "author":
if (isset($pretext['author']) && !empty($pretext['author'])) {
$evclasses[] = $evclassprefix.$pretext['author'];
}
break;
default:
if (isset($row[$evcls]) && !empty($row[$evcls])) {
$evclasses[] = $evclassprefix.$row[$evcls];
}
break;
}
}
$evclasses = ($evclasses) ? ' '. join(' ', $evclasses) : '';
$ignore = $cflag = array();
if ($debug > 1 && $evclasses) {
echo '++ EVENT CLASSES ++';
dmp($evclasses);
}
// Events that start this month
if ($start < $end && $start > $ts_first) {
populateArticleData($row);
// a standard event or start of a multi
if ($showspanned && $multi && !$recur) {
$smd_cal_flag[] = 'multifirst';
}
if ($recur) {
$smd_cal_flag[] = 'recurfirst';
}
if (!$smd_cal_flag) {
$smd_cal_flag[] = 'standard';
}
if ( ( $hol_hit && !in_array('multi',$holidayflags) && in_array('multifirst',$smd_cal_flag) ) || ( $hol_hit && !in_array('standard',$holidayflags) && in_array('standard',$smd_cal_flag) ) ) {
$smd_cal_flag[] = 'cancel';
}
foreach ($smd_cal_flag as $item) {
$cflag[] = $classprefix.$item;
}
$idx = (int)strftime('%d', $start);
$smd_day = $idx;
$smd_week = strftime('%V', $start);
$op = ($thing) ? parse($thing) : (($form) ? parse_form($form) : (($size=="small") ? '' : href($row['Title'], permlinkurl($row), ' title="'.$row['Title'].'"')) );
$events[$idx][] = array('ev' => $op, 'flag' => $smd_cal_flag, 'classes' => (($cflag) ? join(' ',array_merge($cflag, $smd_cal_ucls)) : '').$evclasses, 'posted' => $start_date);
$smd_cal_flag = $cflag = $smd_cal_ucls = array();
}
// Generate a skip array for this event
if ($skipfield && $row[$skipfield] != '') {
$ignore = do_list($row[$skipfield]);
foreach ($ignore as $key => $val) {
$ignore[$key] = date("d-M-Y", strtotime($val)); // Force each date to a known format
}
}
if ($debug > 1) {
echo '++ IGNORE DATES ++';
dmp($ignore);
}
// Calculate the date offsets and check recurring events that fall within the month of interest
if ($stepfield && $row[$stepfield] != '') {
$freq = do_list($row[$stepfield]);
foreach ($freq as $interval) {
$max_loop = 99999; // Yuk, but practically limitless
$interval = str_replace("?month", date('F', gmmktime(0,0,0,$month,1)), $interval);
$interval = str_replace("?year", $year, $interval);
if (strpos($interval, "last") === 0) {
$interval = date("l, F jS Y", strtotime($interval, mktime(12, 0, 0, date("n",mktime(0,0,0,$month,1,$year))+1, 1, $year)));
$max_loop = 1;
} else if (strpos($interval, "first") === 0) {
$interval = date("l, F jS Y", strtotime($interval, mktime(12, 0, 0, (($month>1) ? $month-1 : 12), date("t",mktime(0,0,0,$month-1,1,(($month==1) ? $year-1: $year))), (($month==1) ? $year-1: $year))));
$max_loop = 1;
}
$ts_loop = 0;
$ts_curr = $start;
while ($ts_curr < $end && $ts_loop < $max_loop) {
if ($max_loop == 1) {
$ts_curr = strtotime($interval);
$ts_curr = ($ts_curr < $start || $ts_curr > $end) ? $start : $ts_curr;
} else {
$ts_curr = strtotime($interval, $ts_curr);
}
if ($ts_curr === false) {
$ts_loop++;
break;
} else {
if ($debug > 1) {
dmp("INTERVAL: ". date('d-M-Y H:i:s', $ts_curr));
}
if ($ts_curr < $end && $ts_curr >= $ts_first && $ts_curr != $start) {
// A recurring event. Check it isn't a holiday or to be ignored
populateArticleData($row);
$op = '';
$idx = (int)strftime('%d', $ts_curr);
$smd_cal_flag[] = 'recur';
$show_me = !in_array(date("d-M-Y", $ts_curr), $ignore);
$hol_hit = in_array(date("d-M-Y", $ts_curr), $holidays);
$show_hol = ($hol_hit && !in_array('recur',$holidayflags) ) ? false : true;
if ( !$show_me || !$show_hol ) {
$smd_cal_flag[] = 'cancel';
}
foreach ($smd_cal_flag as $item) {
$cflag[] = $classprefix.$item;
}
// Create the events that appear in the cell but only if they've not appeared before, or are to be ignored
if (($show_me && $show_hol) || $showskipped) {
$smd_day = $idx;
$smd_week = strftime('%V', $ts_curr);
$op = ($recurform) ? parse_form($recurform) : (($thing) ? parse($thing) : (($size=="small") ? '' : href($row['Title'], permlinkurl($row), ' title="'.$row['Title'].'"')) );
}
$used = array();
if (isset($events[$idx]) && $events[$idx] != NULL) {
foreach ($events[$idx] as $ev) {
$used[] = $ev['ev'];
}
}
if (isset($events[$idx]) && $events[$idx] == NULL || !in_array($op, $used)) {
$events[$idx][] = array('ev' => $op, 'flag' => $smd_cal_flag, 'classes' => (($cflag) ? join(' ',array_merge($cflag, $smd_cal_ucls)) : '').$evclasses, 'posted' => $start_date);
}
$smd_cal_flag = $cflag = $smd_cal_ucls = array();
}
$ts_loop++;
}
}
}
} else if ($showspanned && $multi) {
// Non-recurring events may span more than one date but they must still respect ignored dates and holidays
populateArticleData($row);
$lastday = (int)strftime('%d', $end);
$real_lastday = (int)strftime('%d', $real_end);
while (++$idx <= $lastday) {
$op = '';
$multiflag = ($idx==$real_lastday) ? 'multilast' : (($idx==1) ? 'multiprev' : 'multi');
$smd_cal_flag[] = $multiflag;
$thisdate = gmmktime(0, 0, 0, $month, $idx, $year);
$show_me = !in_array(date("d-M-Y", $thisdate), $ignore);
$hol_hit = in_array(date("d-M-Y", $thisdate), $holidays);
$show_hol = ($hol_hit && !in_array('multi',$holidayflags) ) ? false : true;
if ( !$show_me || !$show_hol ) {
$smd_cal_flag[] = 'cancel';
}
foreach ($smd_cal_flag as $item) {
$cflag[] = $classprefix.$item;
}
// Create the spanned event that appears in the cell
if ( ($show_me && $show_hol) || $showskipped) {
$smd_day = $idx;
$smd_week = strftime('%V', $thisdate);
$op = ($spanform) ? parse_form($spanform) : (($thing) ? parse($thing) : (($size=="small") ? '' : href('→', permlinkurl($row), ' title="'.$row['Title'].'"')) );
}
$events[$idx][] = array('ev' => $op, 'flag' => $smd_cal_flag, 'classes' => (($cflag) ? join(' ',array_merge($cflag, $smd_cal_ucls)) : '').$evclasses, 'posted' => $start_date);
$smd_cal_flag = $cflag = $smd_cal_ucls = array();
}
}
}
article_pop();
// Generate the calendar
if( $size == "small" ) {
$calendar = new SMD_Small_Calendar($year, $month, $events, $section, $category);
} else {
$calendar = new SMD_Calendar($year, $month, $events);
}
$calendar->setWeek($week);
$calendar->setGMT($gmt);
$calendar->setLang($lang);
$calendar->setClassLevels($clevs);
$calendar->setClassPrefix($classprefix);
$calendar->setEventPrefix($evclassprefix);
$calendar->setEventWraptag($eventwraptag);
$calendar->setCellForm($cellform);
$calendar->setMYWraptag($mywraptag);
$calendar->setTableID($id);
$calendar->setTableClass($class);
$calendar->setRowClass($rowclass);
$calendar->setCellClass($cellclass);
$calendar->setEmptyClass($emptyclass);
$calendar->setISOWeekClass($isoweekclass);
$calendar->setNavInfo($navpclass,$navnclass,$navparr,$navnarr,$navid);
$calendar->setNavKeep($maintain);
$calendar->setMYClass($myclass);
$calendar->setNameFormat($dayformat, "d");
$calendar->setNameFormat($monthformat, "m");
$calendar->setShowISOWeek($isoweeks);
$calendar->setEYear($earliest);
$calendar->setLYear($latest);
$calendar->setFilterOpts($fopts);
$calendar->setHolidays($holidays);
$calendar->setSelectors(do_list($select), $selectbtn);
$calendar->setFirstDayOfWeek($firstday);
$calendar->setLinkPosted($linkposted);
return $calendar->display($static, $future);
}
class SMD_Calendar extends SMD_Raw_Calendar {
// Override Constructor
// Permits multiple events to show per day
function SMD_Calendar($year,$month,$events) {
$this->events = $events;
$this->SMD_Raw_Calendar($year,$month);
}
// Override dspDayCell to display stuff right
function dspDayCell($theday) {
global $smd_cal_flag, $smd_cal_id, $smd_cal_ucls, $smd_year, $smd_month, $smd_week, $smd_day;
$smd_cal_flag = $smd_cal_ucls = array();
$hasarticle = isset($this->events[$theday]);
$thedate = gmmktime(0, 0, 0, $this->month, $theday, $this->year);
$hol_hit = in_array(date("d-M-Y", $thedate), $this->holidays);
if ($hasarticle) {
$smd_cal_flag[] = 'event';
}
if ($hol_hit) {
$smd_cal_flag[] = 'hols';
}
$cflag = array();
foreach ($smd_cal_flag as $item) {
$cflag[] = $this->classprefix.$item;
}
$tdclass = $this->cellclass . (($cflag) ? ' '.join(' ', $cflag) : '');
$runningclass = (in_array("cell", $this->classlevels) || in_array("cellplus", $this->classlevels)) ? explode(' ', $tdclass) : array();
if($this->year == date('Y',time()+tz_offset() ) and $this->month == date('n',time()+tz_offset() ) and $theday == date('j',time()+tz_offset()) ) {
$smd_cal_flag[] = 'today';
$runningclass[] = $this->classprefix.'today';
}
$out = $flags = array();
if (empty($this->cellform)) {
$out[] = hed($theday,4);
}
if( isset($this->events[$theday]) ) {
$days_events = $this->events[$theday];
foreach($days_events as $ev) {
$evclass = trim($ev['classes']);
$flags = array_merge($flags, $ev['flag']);
if (in_array("cellplus", $this->classlevels)) {
foreach (explode(' ', $evclass) as $evc) {
$runningclass[]= $evc;
}
}
$out[] = ($this->evwraptag) ? tag($ev['ev'], $this->evwraptag, (($evclass && in_array("event", $this->classlevels)) ? ' class="'.$evclass.'"' : '')) : $ev['ev'];
}
}
$runningclass = array_unique($runningclass);
if (in_array("cellplus", $this->classlevels)) {
$smd_cal_flag = array_merge($smd_cal_flag, $flags);
}
if ($this->cellform) {
$thisdate = gmmktime(0, 0, 0, $this->month, $theday, $this->year);
$smd_cal_id = $this->tableID;
$smd_year = $this->year;
$smd_month = $this->month;
$smd_week = strftime("%V", $thisdate);
$smd_day = $theday;
$reps = array(
'{events}' => join('',$out),
'{day}' => $theday,
'{weekday}' => ((is_array($this->dayNameFmt)) ? $this->dayNames[date('w',$thisdate)] : strftime($this->dayNameFmt, $thisdate)),
'{week}' => $smd_week,
'{month}' => $this->month,
'{monthname}' => strftime($this->mthNameFmt, $thisdate),
'{year}' => $this->year,
'{shortyear}' => strftime("%g", $thisdate),
);
$cellout = parse(strtr($this->cellform, $reps));
$carray = array_merge($runningclass, $smd_cal_ucls);
$smd_cal_ucls = array();
return doTag($cellout,'td',join(' ',$carray));
} else {
// Amalgamate the event-level classes and cell-level classes, if required
return doTag(join('',$out),'td',join(' ',$runningclass));
}
}
function display($static=false, $future=false) {
$id = ($this->tableID) ? ' id="'.$this->tableID.'"' : '';
$c[] = $this->dspHeader($static, $future);
$c[] = $this->dspDayNames();
$c[] = $this->dspDayCells();
return doTag(join('',$c),'table',$this->tableclass,$id);
}
function dspHeader($static, $future) {
global $pretext, $smd_week;
$currmo = $this->month;
$curryr = $this->year;
$navpclass = $this->getNavInfo("pc");
$navnclass = $this->getNavInfo("nc");
$navparrow = $this->getNavInfo("pa");
$navnarrow = $this->getNavInfo("na");
$navid = $this->getNavInfo("id");
$navpclass = ($navpclass) ? ' class="'.$navpclass.'"' : '';
$navnclass = ($navnclass) ? ' class="'.$navnclass.'"' : '';
$fopts = $this->fopts;
foreach ($this->maintain as $col) {
switch ($col) {
case "section":
if ($pretext['s']) {
$fopts = array('s' => $pretext['s']) + $fopts;
}
break;
case "article":
if ($pretext['id']) {
$fopts = array('id' => $pretext['id']) + $fopts;
}
break;
case "category":
if ($pretext['c']) {
$fopts = array('c' => $pretext['c']) + $fopts;
}
break;
case "author":
if (gps('author')) {
$fopts = array('author' => gps('author')) + $fopts;
}
break;
case "pg":
if ($pretext['pg']) {
$fopts = array('pg' => $pretext['pg']) + $fopts;
}
break;
case "calid":
if ($this->tableID) {
$fopts = array('calid' => $this->tableID) + $fopts;
}
break;
default:
if (gps($col)) {
$fopts = array($col => gps($col)) + $fopts;
}
break;
}
}
$fopts = array_unique($fopts);
$filters = array();
$filterHid = array();
if (!$static) {
foreach($fopts as $key => $val) {
$filters[] = $key.'='.$val;
$filterHid[] = hInput($key, $val);
}
}
$filterURL = join(a, $filters);
// Week select list
if ($this->useSelector('week') && !$static) {
$currwk = ($this->week) ? $this->week : date('W', strtotime( $curryr."-".$currmo."-1 12:00" ));
for ( $idx = 1; $idx <= 52; $idx++ ) {
$tagatts = ' value="'.$idx.'"';
if ( $idx == $currwk ) $tagatts .= ' selected="selected"';
$optiontags[] = doTag(str_pad($idx, 2, '0', STR_PAD_LEFT), 'option', '', $tagatts);
}
$selector[] = doTag(join(n, $optiontags), 'select', (($this->mywraptag) ? '' : $this->myclass), ' name="w"'.(($this->selbtn) ? '' : ' onchange="submit()"'), '')
. (($this->useSelector('year')) ? '' : hInput('y', $curryr));
$optiontags = array(); // Blank out
}
// Month select list - note mktime has the day forced to 1. If not you get
// bizarre repeated month names on the 31st of some months :-\
if (!$this->useSelector('week')) {
if ($this->useSelector('month') && !$static) {
for ( $idx = 1; $idx <= 12; $idx++ ) {
$tagatts = ' value="'.$idx.'"';
if ( $idx == $currmo ) $tagatts .= ' selected="selected"';
$optiontags[] = doTag(strftime($this->mthNameFmt, gmmktime(12,0,0,$idx,1)), 'option', '', $tagatts);
}
$selector[] = doTag(join(n, $optiontags), 'select', (($this->mywraptag) ? '' : $this->myclass), ' name="m"'.(($this->selbtn) ? '' : ' onchange="submit()"'), '')
. (($this->useSelector('year')) ? '' : hInput('y', $curryr));
$optiontags = array(); // Blank out
} else {
$selector[] = doTag($this->getMonthName(), 'span', (($this->mywraptag) ? '' : $this->myclass));
}
}
// Year select list
$y0 = $this->eyr;
$y1 = $this->lyr;
if ($this->useSelector('year') && ($y0 != $y1) && !$static) {
for ( $idx = $y0; $idx <= $y1; $idx++ ) {
$tagatts = ' value="'.$idx.'"';
if ( $idx == $curryr ) $tagatts .= ' selected="selected"';
$optiontags[] = doTag($idx, 'option', '', $tagatts);
}
$selector[] = doTag(join(n, $optiontags), 'select', (($this->mywraptag) ? '' : $this->myclass), ' name="y"'.(($this->selbtn) ? '' : ' onchange="submit()"'), '')
. (($this->useSelector('month')) ? '' : hInput('m', $currmo));
} else {
$selector[] = doTag($curryr, 'span', (($this->mywraptag) ? '' : $this->myclass));
}
$extras = '';
if (!$static && ( $this->useSelector('month') || $this->useSelector('year') )) {
if ($this->selbtn) {
$extras .= doTag('', 'input', 'smd_cal_input', ' type="submit" value="'.$this->selbtn.'"');
}
$extras .= join('', $filterHid);
}
$urlp = parse_url($pretext['request_uri']);
$selector = '
';
$nav_back_link = $this->navigation($this->year, $this->month, '-', $filterURL);
$nav_fwd_link = $this->navigation($this->year, $this->month, '+', $filterURL);
$nav_back = (!$static && $nav_back_link) ? ''.$navparrow.'' : ' ';
$nav_fwd = (!$static && $future && $nav_fwd_link) ? ''.$navnarrow.'' : ' ';
$c[] = doTag($nav_back,'th');
$c[] = ''.$selector.' | ';
$c[] = doTag($nav_fwd,'th');
return doTag(join('',$c),'tr', 'smd_cal_navrow');
}
function navigation($year,$month,$direction,$flt) {
global $permlink_mode;
if($direction == '-') {
if($month - 1 < 1) {
$month = 12;
$year -= 1;
} else {
$month -= 1;
}
} else {
if($month + 1 > 12) {
$month = 1;
$year += 1;
} else {
$month += 1;
}
}
// Abort if we're about to go out of range
if ($year < $this->eyr || $year > $this->lyr) {
return '';
}
if($permlink_mode != 'messy') {
return "?m=$month".a."y=$year".a.$flt;
} else { // for messy URL's we need to build the entire request string first, then tack on the rest
$out = makeOut('id','s','c','q','pg','p','month');
$r = '?';
foreach($out as $key => $val ) {
$r .= ($val) ? "$key=$val".a : '';
}
return $r."m=$month".a."y=$year".a.$flt;
}
}
}
class SMD_Small_Calendar extends SMD_Calendar {
var $section = '';
var $category = '';
function SMD_Small_Calendar($year,$month,$events,$section,$category) {
$this->section = $section;
$this->category = $category;
$this->SMD_Calendar($year,$month,$events);
}
function dspDayCell($theday) {
global $permlink_mode;
$hasarticle = isset($this->events[$theday]);
$class[] = $this->cellclass.' ' . (($hasarticle) ? $this->classprefix.'event' : '');
if ((in_array( date('d-M-Y', gmmktime( 0, 0, 0, $this->month, $theday, $this->year) ), $this->holidays)) ) {
$class[] = $this->classprefix.'hols';
}
if($this->year == date('Y',time()+tz_offset() ) and $this->month == date('n',time()+tz_offset() ) and $theday == date('j',time()+tz_offset()) ) {
$class[] = $this->classprefix.'today';
}
if( isset($this->events[$theday]) ) {
$days_events = $this->events[$theday];
foreach($days_events as $ev) {
$evclass = trim($ev['classes']);
foreach (explode(' ', $evclass) as $evc) {
$class[]= $evc;
}
$out[] = ($this->evwraptag) ? tag($ev['ev'], $this->evwraptag, (($evclass) ? ' class="'.$evclass.'"' : '')) : $ev['ev'];
}
$use_posted = false;
foreach ($this->linkposted as $dlinks) {
if (in_array($dlinks, $class)) {
$use_posted = true;
break;
}
}
if( $permlink_mode != 'year_month_day_title' ) {
$linkdate = ($use_posted) ? $ev['posted'] : $this->year.'-'.$this->doubledigit($this->month).'-'.$this->doubledigit($theday);
$href = ' href="'.hu.'?date='.$linkdate;
if($this->section) { $href = $href.a.'s='.$this->section; }
if($this->category) { $href = $href.a.'c='.$this->category; }
$href .= '"';
} else {
$section = ($this->section) ? $this->section.'/' : '';
$linkdate = ($use_posted) ? preg_replace("-", "/", $ev['posted']) : $this->year.'/'.$this->doubledigit($this->month).'/'.$this->doubledigit($theday);
$href = ' href="'.hu.$section.$linkdate.'"';
}
$c[] = doTag($theday.join('',$out),'a','',$href);
} else {
$c[] = $theday;
}
return doTag(join('',$c),'td',join(' ',$class));
}
function doubledigit($n) {
if($n < 10) { $n = '0'.(int)$n; }
return $n;
}
}
/**
* Basic Calendar data and display
* http://www.oscarm.org/static/pg/calendarClass/
* @author Oscar Merida
* @created Jan 18 2004
* @package goCoreLib
*/
class SMD_Raw_Calendar {
var $gmt = 1;
var $lang;
var $year;
var $eyr;
var $lyr;
var $month;
var $week;
var $dayNameFmt;
var $mthNameFmt;
var $dayNames;
var $startDay;
var $selectors;
var $selbtn;
var $showISOWeek;
var $ISOWeekHead;
var $ISOWeekCell;
var $endDay;
var $firstDayOfWeek = 0;
var $startOffset = 0;
var $classlevels;
var $classprefix;
var $evclassprefix;
var $evwraptag;
var $mywraptag;
var $rowclass;
var $cellclass;
var $emptyclass;
var $isoclass;
var $navpclass;
var $navnclass;
var $navparrow;
var $navnarrow;
var $navid;
var $myclass;
var $fopts;
var $holidays;
var $linkposted;
var $cellform;
var $tableID;
var $maintain;
/**
* Constructor
*
* @param integer, year
* @param integer, month
* @return object
* @public
*/
function SMD_Raw_Calendar ( $yr, $mo ) {
$this->setYear($yr);
$this->setMonth($mo);
$this->setClassPrefix('smd_cal_');
$this->startTime = strtotime( "$yr-$mo-01 00:00" );
$this->startDay = date( 'D', $this->startTime );
$this->endDay = date( 't', $this->startTime );
$this->endTime = strtotime( "$yr-$mo-".$this->endDay." 23:59" );
$this->setNameFormat('%a', 'd');
$this->setNameFormat('%B', 'm');
$this->setFirstDayOfWeek(0);
$this->setShowISOWeek('');
$this->setTableID('');
$this->setTableClass('');
}
// ==== end Calendar ================================================
// Getters
function useSelector($val) { return in_array($val, $this->selectors); }
function getDayName($day) { return ($this->dayNames[$day%7]); }
function getMonthName() { return strftime( $this->mthNameFmt, $this->startTime ); }
function getNavInfo($type) {
$r = '';
switch ($type) {
case "id": $r = $this->navid; break;
case "pc": $r = $this->navpclass; break;
case "nc": $r = $this->navnclass; break;
case "pa": $r = $this->navparrow; break;
case "na": $r = $this->navnarrow; break;
}
return $r;
}
// Setters
function setGMT($b){ $this->gmt = $b; }
function setLang($code){ $this->lang = $code; }
function setCellForm($frm){ $this->cellform = $frm; }
function setTableID($id){ $this->tableID = $id; }
function setYear($yr){ $this->year = $yr; }
function setEYear($yr){ $this->eyr = $yr; }
function setLYear($yr){ $this->lyr = $yr; }
function setMonth($mth){ $this->month = (int)$mth; }
function setWeek($wk){
if ($wk) {
$this->week = (int)$wk;
$this->month = safe_strftime("%m", gmmktime (1,1,1,1,7*$wk,$this->year));
}
}
function setNavKeep($ar){ $this->maintain = $ar; }
function setShowISOWeek($val) {
$this->showISOWeek = ($val) ? true : false;
if ($val) {
$val = do_list($val);
$this->ISOWeekHead = $val[0];
$this->ISOWeekCell = (isset($val[1])) ? $val[1] : '{week}';
}
}
function setClassLevels($cls){ $this->classlevels = $cls; }
function setClassPrefix($cls){ $this->classprefix = $cls; }
function setEventPrefix($cls){ $this->evclassprefix = $cls; }
function setEventWraptag($wrap){ $this->evwraptag = $wrap; }
function setMYWraptag($wrap){ $this->mywraptag = $wrap; }
function setTableClass($cls) { $this->tableclass = ($cls) ? $this->classprefix.$cls : ''; }
function setRowClass($cls){ $this->rowclass = ($cls) ? $this->classprefix.$cls : ''; }
function setCellClass($cls){ $this->cellclass = ($cls) ? $this->classprefix.$cls : ''; }
function setEmptyClass($cls){ $this->emptyclass = ($cls) ? $this->classprefix.$cls : ''; }
function setISOWeekClass($cls){ $this->isoclass = ($cls) ? $this->classprefix.$cls : ''; }
function setNavInfo($clsp, $clsn, $arrp, $arrn, $nid){
$this->navpclass = ($clsp) ? $this->classprefix.$clsp : '';
$this->navnclass = ($clsn) ? $this->classprefix.$clsn : '';
$this->navparrow = ($arrp) ? $arrp : '';
$this->navnarrow = ($arrn) ? $arrn : '';
$this->navid = ($nid) ? $this->classprefix.$nid : '';
}
function setMYClass($cls){ $this->myclass = ($cls) ? $this->classprefix.$cls : ''; }
function setFilterOpts($f) { $this->fopts = $f; }
function setLinkPosted($dl) {
foreach ($dl as $dval) {
$this->linkposted[] = $this->classprefix.$dval;
}
}
function setHolidays($hols) { $this->holidays = $hols; }
function setSelectors($sel, $btn) { $this->selectors = $sel; $this->selbtn = $btn; }
function setFirstDayOfWeek($d) {
$this->firstDayOfWeek = ((int)$d <= 6 and (int)$d >= 0) ? (int)$d : 0;
$this->startOffset = date( 'w', $this->startTime )-$this->firstDayOfWeek;
if ( $this->startOffset < 0 ) {
$this->startOffset = 7 - abs($this->startOffset);
}
}
/**
* frm: any valid PHP strftime() string or ABBR/FULL
* typ: d to set day, m to set month format
*/
function setNameFormat($frm, $typ="d") {
switch ($frm) {
case "FULL":
$fmt = ($typ == 'd') ? "%A" : "%B";
break;
case "ABBR":
$fmt = ($typ == 'd') ? "%a" : "%b";
break;
default:
if ($typ == 'd') {
if (strpos($frm, '%') === 0) {
$fmt = $frm;
} else {
$frm = trim($frm, '{}');
$frm = do_list($frm);
$fmt = $frm;
}
} else {
$fmt = $frm;
}
break;
}
if ($typ == "d") {
$this->dayNameFmt = $fmt;
$this->dayNames = array();
// This is done to make sure Sunday is always the first day of our array
// Unix time gets a little funky at the beginning depending upon your timezone.
$serveroffset = gmmktime(0,0,0) - mktime(0,0,0);
$start = ($serveroffset < 0) ? 4 : 3;
$end = $start + 7;
for($i=$start; $i<$end; $i++) {
if (is_array($fmt)) {
$this->dayNames[] = $fmt[$i-$start];
} else {
$this->dayNames[] = ucfirst(safe_strftime($fmt, 86400*$i - tz_offset(), $this->gmt, $this->lang ));
}
}
} else {
$this->mthNameFmt = $fmt;
}
}
/**
* Returns markup for displaying the calendar.
* @return
* @public
*/
function display ( ) {
$id = ($this->tableID) ? ' id="'.$this->tableID.'"' : '';
$c[] = '';
$c[] = $this->dspDayNames();
$c[] = $this->dspDayCells();
$c[] = '
';
return join('',$c);
}
// ==== end display ================================================
/**
* Displays the row of day names.
* @return string
* @private
*/
function dspDayNames ( ) {
$c[] = '';
$i = $this->firstDayOfWeek;
$j = 0; // count number of days displayed
$end = false;
if ($this->showISOWeek) {
$c[] = "".$this->ISOWeekHead." | ";
}
for($j = 0; $j<=6; $j++, $i++) {
if($i == 7) { $i = 0; }
$c[] = ''.$this->getDayName($i)." | ";
}
$c[] = '
';
return join('',$c);
}
// ==== end dspDayNames ================================================
/**
* Displays all day cells for the month
*
* @return string
* @private
*/
function dspDayCells ( ) {
$i = 0; // cell counter
$emptyClass = $this->emptyclass;
$isoClass = $this->isoclass;
$rowClass = $this->rowclass;
$rowClass = ($rowClass) ? ' class="'.$rowClass.'"' : '';
$c[] = '';
if ($this->showISOWeek) {
$wkcell = strtr($this->ISOWeekCell, array('{week}' => date( 'W', $this->startTime ) ));
$c[] = ''.$wkcell.' | ';
}
// first display empty cells based on what weekday the month starts in
for( $j=0; $j<$this->startOffset; $j++ ) {
$i++;
$c[] = ' | ';
} // end offset cells
// write out the rest of the days, at each sunday, start a new row.
for( $d=1; $d<=$this->endDay; $d++ ) {
$i++;
$c[] = $this->dspDayCell( $d );
if ( $i%7 == 0 ) { $c[] = '
'; }
if ( $d<$this->endDay && $i%7 == 0 ) {
$c[] = '';
if ($this->showISOWeek) {
$wkcell = strtr($this->ISOWeekCell, array('{week}' => date( 'W', strtotime( $this->year."-".$this->month."-".(int)($d + 1) ." 00:00" )) ));
$c[] = ''.$wkcell.' | ';
}
}
}
// fill in the final row
$left = 7 - ( $i%7 );
if ( $left < 7) {
for ( $j=0; $j<$left; $j++ ) {
$c[] = ' | ';
}
$c[] = "\n\t
";
}
return join('',$c);
}
// ==== end dspDayCells ================================================
/**
* outputs the contents for a given day
*
* @param integer, day
* @abstract
*/
function dspDayCell ( $day ) {
return ''.$day.' | ';
}
// ==== end dayCell ================================================
} // end class
// Perform one of 2 types of test: a flag-based test, or an info-based test
function smd_if_cal($atts, $thing) {
global $smd_cal_flag, $smd_cal_id, $smd_year, $smd_month, $smd_week, $smd_day;
extract(lAtts(array(
'flag' => '', // event, standard, recur(first), multi(first,last,prev), cancel, hols, today, SMD_ANY
'calid' => '',
'year' => '',
'month' => '',
'week' => '',
'day' => '',
'logic' => 'and',
'debug' => '0',
), $atts));
$flag = do_list($flag);
$ctr = $num = 0;
if ($debug) {
dmp($atts);
}
if ($flag && $flag[0] != '') {
$num += count($flag);
foreach ($flag as $whatnot) {
if (empty($whatnot)) continue;
$ctr += (in_array($whatnot, $smd_cal_flag) || ($whatnot == 'SMD_ANY' && !empty($smd_cal_flag))) ? 1 : 0;
}
}
if ($calid) {
$num++;
$ctr += ($smd_cal_id === $calid) ? 1 : 0;
}
foreach (array("year", "month", "week", "day") as $test) {
$tester = $$test;
$gbl = 'smd_'.$test;
$compare = $$gbl;
if ($tester) {
$num++;
preg_match('/([!=<>]+)?([\d]+)/', $tester, $matches);
if ($debug) {
dmp("TEST IF: ". $compare. (($matches[1]) ? $matches[1] : '=') . $matches[2] );
}
switch ($matches[1]) {
case "!":
$ctr += ($compare!=$matches[2]) ? 1 : 0;
break;
case ">":
$ctr += ($compare>$matches[2]) ? 1 : 0;
break;
case ">=":
$ctr += ($compare>=$matches[2]) ? 1 : 0;
break;
case "<":
$ctr += ($compare<$matches[2]) ? 1 : 0;
break;
case "<=":
$ctr += ($compare<=$matches[2]) ? 1 : 0;
break;
default:
$ctr += ($compare==$matches[2]) ? 1 : 0;
break;
}
}
}
$result = (($ctr === $num && $logic == "and") || $ctr > 0 && $logic == "or") ? true : false;
return parse(EvalElse($thing, $result));
}
function smd_cal_info($atts) {
global $pretext, $thisarticle, $smd_cal_flag, $smd_cal_id, $smd_year, $smd_month, $smd_week, $smd_day;
extract(lAtts(array(
'type' => 'flag', // flag, year, month, week, day, calid, section, category, author
'join' => ' ',
'join_prefix' => 'SMD_AUTO',
'html' => 0,
'escape' => 'html',
), $atts));
$join = ($html) ? a : $join; // html mode forces ampersand join
$type = do_list($type);
$ret = array();
foreach ($type as $item) {
switch ($item) {
case "flag":
$ret[] = (($join_prefix=="SMD_AUTO") ? $join : '').join($join, $smd_cal_flag);
break;
case "year":
if ($smd_year) {
$ret[] = (($html) ? 'y=' : '') . $smd_year;
}
break;
case "month":
if ($smd_month) {
$ret[] = (($html) ? 'm=' : '') . $smd_month;
}
break;
case "week":
if ($smd_week) {
$ret[] = (($html) ? 'w=' : '') . $smd_week;
}
break;
case "day":
if ($smd_day) {
$ret[] = (($html) ? 'd=' : '') . $smd_day;
}
break;
case "section":
if ($pretext['s']) {
$ret[] = (($html) ? 's=' : '') . $pretext['s'];
}
break;
case "category":
if ($pretext['c']) {
$ret[] = (($html) ? 'c=' : '') . $pretext['c'];
}
break;
case "author":
if ($thisarticle == NULL) {
$currauthor = '';
} else {
$currauthor = author(array());
}
if ($currauthor) {
$ret[] = (($html) ? 'author=' : '') . $currauthor;
}
break;
case "calid":
if ($smd_cal_id) {
$ret[] = (($html) ? 'calid=' : '') . $smd_cal_id;
}
break;
}
}
$out = (($join_prefix=="SMD_AUTO") ? (($html) ? '?' : '') : $join_prefix).join($join, $ret);
return ($escape=='html') ? htmlspecialchars($out) : $out;
}
function smd_cal_now($atts) {
global $dateformat;
extract(lAtts(array(
'format' => $dateformat,
'gmt' => '',
'lang' => '',
), $atts));
return safe_strftime($format, time(), $gmt, $lang);
}
// Set user-defined classes for a cell
function smd_cal_class($atts) {
global $smd_cal_ucls;
extract(lAtts(array(
'name' => '',
), $atts));
$name = do_list($name);
$smd_cal_ucls = array_merge($smd_cal_ucls, $name);
}
// replacement(ish) tag that understands how to handle recurring events
function smd_article_event($atts, $thing='') {
global $prefs, $pretext, $thispage;
extract(lAtts(array(
'time' => 'any',
'type' => 'standard,recur,multi', // type of event to show
'expired' => '', // 0=no, 1=yes publish expired events, empty=use prefs
'id' => '',
'category' => '',
'section' => '',
'author' => '',
'status' => 'live',
'sort' => '',
'form' => '',
'stepfield' => '',
'skipfield' => '',
'month' => '',
'from' => '', // start date
'to' => '', // end date
'offset' => 0,
'limit' => '10',
'eventlimit' => '10', // max number of recurring events to create per real event
'pageby' => '',
'pgonly' => '',
'wraptag' => '',
'break' => '',
'class' => '',
'debug' => 0,
), $atts));
// Filters
$filtSQL = $subSQL = array();
if($category) {
$tmp = doQuote(join("','", doSlash(do_list($category))));
$filtSQL[] = '( Category1 IN ('.$tmp.') OR Category2 IN ('.$tmp.') )';
}
if($section) {
$filtSQL[] = 'Section IN ('.doQuote(join("','", doSlash(do_list($section)))).')';
}
if($author) {
$filtSQL[] = 'AuthorID IN ('.doQuote(join("','", doSlash(do_list($author)))).')';
}
if($id) {
$filtSQL[] = 'ID IN ('.join(',', array_map('intval', do_list($id))).')';
}
$type = do_list($type);
$pageby = (empty($pageby) ? $limit : $pageby);
foreach ($type as $evtyp) {
switch($evtyp) {
case 'standard':
if ($stepfield) {
$subSQL[] = "(".$stepfield." = '' AND Expires = ".NULLDATETIME.")";
}
break;
case 'recur':
if ($stepfield) {
$subSQL[] = "(".$stepfield." != '')";
}
break;
case 'multi':
if ($stepfield) {
$subSQL[] = "(".$stepfield." = '' AND Expires != ".NULLDATETIME.")";
}
break;
}
}
if ($subSQL) {
$filtSQL[] = '('.join(' OR ', $subSQL).')';
}
$status = ($status) ? $status : 'live'; // in case status has been emptied
$status = do_list($status);
$stati = array();
foreach ($status as $stat) {
if (empty($stat)) {
continue;
} else if (is_numeric($stat)) {
$stati[] = $stat;
} else {
$stati[] = getStatusNum($stat);
}
}
$filtSQL[] = 'Status IN ('.doQuote(join("','", $stati)).')';
$expired = ($expired) ? $expired : $prefs['publish_expired_articles'];
if (!$expired) {
$filtSQL[] = '(now() <= Expires OR Expires = '.NULLDATETIME.')';
}
// Sorting rules: data is sorted once as it is extracted via SQL and then again after the fake dates have been inserted
$sort = (empty($sort)) ? 'Posted asc' : $sort;
$sort = do_list($sort);
$sortPrefix = "SORT_";
$sortOrder = array();
for ($idx = 0; $idx < count($sort); $idx++) {
$sorties = explode(' ', $sort[$idx]);
if (count($sorties) <= 1) {
$sorties[1] = "asc";
}
$sorties[1] = $sortPrefix.(($sorties[1] == "desc") ? 'DESC' : 'ASC');
$sortOrder[] = array("by" => $sorties[0], "dir" => $sorties[1]);
}
$filtSQL = join(' AND ', $filtSQL);
$filtSQL .= ' ORDER BY '.join(',',doSlash($sort));
$grabCols = '*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires';
$evlist = safe_rows($grabCols, 'textpattern', $filtSQL, $debug);
if ($debug>2) {
echo "++ RECORD SET ++";
dmp($evlist);
}
$all_evs = $ev_tally = array();
$now = time();
// Pass 1: expand any recurring dates and collate all events that fall within the alloted ranges
foreach ($evlist as $row) {
$ev_posted = $row['uPosted'];
$ev_expires = $row['uExpires'];
$ev_day = date('j', $ev_posted);
$ev_month = date('m', $ev_posted);
$ev_year = date('Y', $ev_posted);
$ignore = array();
// Generate a skip array for this event
if ($skipfield && $row[$skipfield] != '') {
$ignore = do_list($row[$skipfield]);
foreach ($ignore as $key => $val) {
$ignore[$key] = date("d-M-Y", strtotime($val)); // Force each date to a known format
}
}
if ($debug > 1) {
echo '++ IGNORE DATES ++';
dmp($ignore);
}
// Does the event deserve to be in the results?
if (smd_include_event($ev_posted, $now, $ignore, $time, $from, $to, $month)) {
$all_evs[] = $row;
$ev_tally[$row['Posted']] = (isset($ev_tally[$row['Posted']])) ? $ev_tally[$row['Posted']]+1 : 1;
}
if ($stepfield && $row[$stepfield] != '') {
$freq = do_list($row[$stepfield]);
$monthly = false;
$currstamp = $ev_posted;
$currmonth = $ev_month;
$curryear = $ev_year;
foreach ($freq as $interval) {
$fakerow = $row;
for($idx = 0; $idx < 99999; $idx++) {
$lastamp = $currstamp;
if ((isset($ev_tally[$row['Posted']]) && ($ev_tally[$row['Posted']] >= $eventlimit)) || ($to && $currstamp > strtotime($to))) {
break;
}
$ival = str_replace("?month", date('F', gmmktime(0,0,0,$currmonth,1)), $interval);
$ival = str_replace("?year", $curryear, $interval);
if (strpos($ival, "last") === 0) {
$ival = date("l, F jS Y", strtotime($ival, mktime(12, 0, 0, date("n",mktime(0,0,0,$currmonth,1,$curryear))+1, 1, $curryear)));
$monthly = true;
} else if (strpos($ival, "first") === 0) {
$ival = date("l, F jS Y", strtotime($ival, mktime(12, 0, 0, (($currmonth>1) ? $currmonth-1 : 12), date("t",mktime(0,0,0,$currmonth-1,1,(($currmonth==1) ? $curryear-1: $curryear))), (($currmonth==1) ? $curryear-1: $curryear))));
$monthly = true;
}
if ($monthly) {
$currstamp = strtotime($ival);
} else {
$currstamp = strtotime($ival, $currstamp);
}
if ($currstamp - $lastamp < 0) {
break; // PHP_INT_MAX exceeded
}
if ($currstamp !== false) {
if ($debug > 1) {
dmp("INTERVAL: ". $currstamp . ' // ' .date('d-M-Y H:i:s', $currstamp));
}
if (($currstamp < $ev_expires || $ev_expires == '0') && ($currstamp != $ev_posted)) {
$show_me = smd_include_event($currstamp, $now, $ignore, $time, $from, $to, $month);
if ($show_me) {
$fakerow['Posted'] = date("Y-m-d H:i:s", $currstamp);
$fakerow['uPosted'] = $currstamp;
$all_evs[] = $fakerow;
$ev_tally[$row['Posted']] = (isset($ev_tally[$row['Posted']])) ? $ev_tally[$row['Posted']]+1 : 1;
}
} else {
break;
}
}
// Increment the month/year ready for the next interval
if ($monthly) {
$curryear = ($currmonth==12) ? $curryear+1 : $curryear;
$currmonth = ($currmonth==12) ? 1 : $currmonth+1;
}
}
if ($debug>1) {
if (isset($ev_tally[$row['Posted']])) {
dmp("TALLY: ". $ev_tally[$row['Posted']]);
}
}
}
}
}
if ($debug>2) {
echo "++ PRE-SORTED ++";
dmp($all_evs);
}
// Make up an array_multisort arg list and execute it
foreach($all_evs as $key => $row) {
foreach ($row as $identifier => $item) {
$varname = "col_".$identifier;
${$varname}[$key] = $item;
}
}
for ($idx = 0; $idx < count($sortOrder); $idx++) {
$sortargs[] = '$col_'.$sortOrder[$idx]['by'];
$sortargs[] = $sortOrder[$idx]['dir'];
}
$sortit = 'array_multisort('.implode(", ",$sortargs).', $all_evs);';
eval($sortit);
if ($debug>2) {
echo "++ POST-SORTED ++";
dmp($all_evs);
}
// Handle paging
$grand_total = count($all_evs);
$total = $grand_total - $offset;
$numPages = ceil($total/$pageby);
$pg = (!$pretext['pg']) ? 1 : $pretext['pg'];
$pgoffset = $offset + (($pg - 1) * $pageby);
// send paging info to txp:newer and txp:older
$pageout['pg'] = $pg;
$pageout['numPages'] = $numPages;
$pageout['s'] = $pretext['s'];
$pageout['c'] = $pretext['c'];
$pageout['grand_total'] = $grand_total;
$pageout['total'] = $total;
if (empty($thispage))
$thispage = $pageout;
if ($pgonly)
return;
// Pass 2: iterate over the new array obeying any offset/limit. Anything in the range gets populated and parsed
$out = array();
$ctr = 0;
article_push();
foreach ($all_evs as $idx => $row) {
if ($idx >= $pgoffset && $ctr < $limit) {
populateArticleData($row);
$out[] = ($thing) ? parse($thing) : (($form) ? parse_form($form) : href($row['Posted'], permlinkurl($row), ' title="'.$row['Title'].'"') );
$ctr++;
}
}
article_pop();
return doWrap($out, $wraptag, $break, $class);
}
// Check the passed timestamp against every time restriction and return true if it passes them all
function smd_include_event($ts, $now, $ign, $time, $from, $to, $month) {
$show = array();
$show[] = !in_array(date("d-M-Y", $ts), $ign);
switch($time) {
case "any": break;
case "future": $show[] = ($ts > $now) ? true : false; break;
default : $show[] = ($ts < $now) ? true : false; break; // The past
}
if ($from) { $show[] = ($ts >= strtotime($from)) ? true : false; }
if ($to) { $show[] = ($ts <= strtotime($to)) ? true : false; }
if ($month) { $show[] = (date("Y-m", $ts) == $month) ? true : false; }
return (!in_array(0, $show)) ? true : false;
}