This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DESCRIPTION: The basic components of KOB are: 1) Posting - (:blogpostbox:) 2) Digest - (:blogdigest group=GROUP:) 3) Archive - (:blogarchive group=GROUP monthsback=AA wrap=B:) 4) Syndication - ?action=blogrss RELEASE HISTORY: v1.1.0-beta1 released December 12th, 2005. Kind-of Blog is based on two existing PmWiki recipes: 1) Wiki Calendar, v0.3.22 by John Rank 2) RSS Simple, v1.1 by Steffen Burmeister See the CHANGELOG for all the gory details. TODO: - Globalize RSS configuration - digest by month - limit digest entries by date - extract titles only - sync. post with PmWiki post - ese EditTitle.php to customize the edit form - edit directive with GUI - name-based storage model - seperate pages for every entry - move to attributes-based system - Audit the global variable calls - Audit the utility functions - Audit archive styles */ /* =============== Configuration =============== */ SDV($max_blog_entries, 6); // This configures how weekdays are presented. // 0 - american style, Sun to Sat // 1 - european style, Mon to Sun SDV($calendar_weekstyle, 0); // FIXME: (1, sun does not show up) // How many months after we should wrap and start a new row. SDV($calendar_month_wrap, 2); // How many months altogether to show on the calendar. SDV($calendar_months_number, 12); // Whether to display non-existent date entries in the calendar as day or day? // Enter 'true' to use the wiki '?' convention for non-existent entries SDV($day_as_wiki, false); // Set depending on whether you need [[Page?logdate= or [[Page&logdate= SDV($url_connector,"?"); // This configures how dates are presented. (NOT IN USE RIGHT NOW) // 0 - american style, 11/17/2002 // 1 - european style, 17.11.2002 // 2 - international style, 2002-11-17 SDV($calendar_datestyle,0); SDV($space_date_titles,1); SDV($SpaceDateString,'-'); /* --------------- Blog RSS Configuration --------------- */ SDV($RssTitle, "Your Feed Title"); SDV($RssLink, "http://www.yourdomain.com"); SDV($RssDesc, "Your Feed Description"); SDV($RssCopyright, "Your Copyright Information"); SDV($RssEditor, "you@yourdomain.com"); SDV($RssWebMaster, "you@yourdomain.com"); SDV($RssLanguage, "en-US"); // You probably shouldn't have to change these SDV($RssMaxItems, 0); SDV($RssItems, array()); // Function to call when the RSS action is triggered SDV($HandleActions['blogrss'],'HandleBlogRss'); /* --------------- Posting --------------- */ // TODO: add option for GUI controls // TODO: ^ tie this to the default PmWiki edit mechanism SDV($BlogFormFmt, "

\$BlogTitle




"); /* --------------- Stylesheet and Appearance --------------- */ // NOTE: To change the way blog entries are formatted, look at // the format_kob_entrystart() function -- you can do whatever you // want in there. In the future, I plan to support the most popular // options as here. // bugfix - v1.1.0 - $FarmPubDirUrl -> $PubDirUrl $HTMLHeaderFmt[] = ""; // Blog entry style rules $blogTimestampStyle = 'blog-timestamp'; // Class used by timestamps $blogPermalinkStyle = 'blog-permalink'; // Class used by permalinks // Alternating classes seperating entries $blogEntry1 = 'blog-entry1'; $blogEntry2 = 'blog-entry2'; // Archive style rules (not yet in use) $blogTodayEntryStyle = 'blog-today-entry'; // Current date, with entries $blogTodayNoentryStyle = 'blog-today-noentry'; // Current date, no entry $blogDateEntryStyle = 'blog-date-entry'; // Other date w/an entry $blogDateNoentryStyle = 'blog-date-noentry'; // Other date w/out an entry $blogBlankCellStyle = 'blog-blank-cell'; // Empty cells at the start/end of months $blogNonexistentDateStyle = 'blog-nonexistent-date'; // Wikilink w/out an entry // This is where we format the way the blog entry appears -- // Move things around, add text, etc, just make sure the variables // appear in there somewhwere // // For date formatting, arrange the variables, as outlined here: // http://us3.php.net/strftime // // NOTE: The heading expects wiki markup, while the date and permalink // are mixes of HTML and markup. I'm having trouble with divs in // markup, so this will have to do for now. It'll be fixed in a // later version. // // NOTE: If you want the permalink before the timestamp, just reorder // the array elements! // $kobEntryFmt = array( title => '!!! $title', timestamp => '
Posted on %b. %d, %Y at %I:%M %p
', permalink => '
[[$permalink | Permanent link]]
' ); /* --------------- Translations --------------- */ // Month and day names in chosen language $shortdaynames = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); $longdaynames = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'); $monthnames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); // TODO: Figure out which of these is in use $period = 'period'; $default_date_text = 'From the wiki calendar'; $WikilogHomeText = 'Calendar'; $DefaultBlogTitle = 'New Blog Entry'; // Submit form text $DateText = 'Date'; $HeadlineText = 'Headline'; $StoryText = 'Story'; $AuthorText = 'Author'; $PostText = ' Post '; $ResetText = 'Reset'; /* ==================== CODE STARTS HERE ===================== */ /* --------------- Viewing --------------- */ // NOTE: Viewing blog entries involves these two directives. // The first opens a containing div, parses the entry's arguments // and formats them accordingly. The second closes the containing // div. The actual blog entry is handled by PmWiki as normal. // So to edit how timestamps and permalinks appear, you'll want // to play around with the format_kob_entrystart() function below. // NOTE: See notes in the configuration section above. Markup('blogentry', 'directives', "/\(:blogentry\s+(.*):\)/e", "format_kob_entrystart(PSS('$1'))"); Markup('blogentryend', 'directives', "/\(:blogentryend:\)/e", "format_kob_entryend()"); /** * FORMAT_KOB_ENTRYSTART - Formats blog entry metadata. * * args: raw arguments * returns: formatted string of HTML * */ function format_kob_entrystart($match) { global $even_entry, $blogEntry1, $blogEntry2; global $kobEntryFmt; global $blogTimestampStyle, $blogPermalinkStyle; // Parse the raw arguments $args = ParseArgs($match); // Make a copy of the entry format $entryFmt = $kobEntryFmt; // Alternate between container div classes if($even_entry == false) { $num = 1; $even_entry = true; } else { $num = 2; $even_entry = false; } $class = 'blogEntry' . $num; // Start building the string here (wrap the entry in // a div; this will be closed by format_kob_entryend()) $string = "
\n"; // These statements look pretty complicated -- we have some generic // formats in $entryFmt. All we're doing is replacing the // variables with the real values from the entry (in $args). // // TODO: I think $FmtV[] would be useful here... maybe next time ;-) // $entryFmt['title'] = MarkupToHTML('', str_replace('$title', $args['title'], $entryFmt['title'])); $entryFmt['timestamp'] = strftime($entryFmt['timestamp'], strtotime($args['time'])); $entryFmt['timestamp'] = str_replace('$blogTimestampStyle', $blogTimestampStyle, $entryFmt['timestamp']); $entryFmt['permalink'] = str_replace('$permalink', $args['permalink'], $entryFmt['permalink']); $entryFmt['permalink'] = str_replace('$blogPermalinkStyle', $blogPermalinkStyle, $entryFmt['permalink']); // Add all the formatted pieces to the string -- since they're in // an associative array, we can just reorder array elements to // automagically reorder the print order... pretty cool! foreach($entryFmt as $entry => $value) { $string .= $value . "\n"; } return $string; } /** * FORMAT_KOB_ENTRYEND - Adds any closing formatting. * * args: none * returns: formatted string of wiki markup * * NOTE: This usually returns just the closing div tag. * */ function format_kob_entryend() { return "
\n"; } /* ----------------- Posting ----------------*/ // Handle incoming entries from the post form if($action == 'postentry') { SDV($HandleActions['postentry'],'HandleBlogPost'); } // Handle the original form else { // This expands the (:blogpostbox:) directive to the actual wiki-code Markup('wbox', '>links', '/\(:blogpostbox(chrono)?\s*(.*?):\)/e', "'<:block>'.Keep(str_replace('\$BlogTitle',SetBlogTitle('$2'), str_replace('\$StoryDate',select_calendar_date(\$pagename), str_replace('\$Chrono','$1', FmtPageName(\$GLOBALS['BlogFormFmt'],\$pagename)))))"); // TODO: When the markup conversion is triggered, we should also // assert edit mode, so skins can adjust the skin accordingly } /** * HANDLE_BLOG_POST - Take post data and create a new blog entry. * * args: pagename * returns: nothing * * entry format: * * (:blogentry title="TITLE" time="ISO" permalink="GROUP.PAGE":) * WIKI MARKUP * (:blogentryend:) * */ function HandleBlogPost($pagename) { global $_POST, $TimeFmt, $SpaceDateString, $blogTimestampStyle, $blogPermalinkStyle; // Use the date to determine the blog entry's page name $date = str_replace($SpaceDateString, '', $_POST['storydate']); $blog_entry_name = FmtPageName('$Group', $pagename) . ".$date"; // Get the entry title $blog_entry_title = $_POST['headline']; // Use the date from the post form to build the timestamp $blog_entry_date = $_POST['storydate']; $blog_entry_time = strftime("%H:%M", time()); $blog_entry_unix_time = strtotime("$blog_entry_date $blog_entry_time"); $blog_entry_timestamp = strftime("%Y-%m-%d %H:%M", $blog_entry_unix_time); // Stitch the components together to form the complete blog entry $blog_entry = "(:blogentry title=\"$blog_entry_title\" time=\"$blog_entry_timestamp\" permalink=\"$blog_entry_name\":)\n" . $_POST['text'] . "\n" . "(:blogentryend:)\n\n\n\n"; // If a blog entry already exists, append the latest post // TODO: We could create seperate pages for each entry // here, if we so desired if(PageExists($blog_entry_name)) { $page = RetrieveAuthPage($blog_entry_name, "edit"); // TODO: If we decide we want to offer order flexibility, here's // where we could reorder the append mechanism $_POST['text'] = $blog_entry . $page['text']; } else { $_POST['text'] = $blog_entry; } // Now that we have the updated blog entry in the POST variable, // kick over to PmWiki for the actual file I/O. HandleEdit($blog_entry_name); } /* --------------- Digest --------------- */ // Handle the digest much like the archive above Markup('blogdigest', 'directives', "/^\(:blogdigest?(\s+group=($GroupPattern)){0,1}+(\s+startdate=([0-9]{8})){0,1}+(\s+weeksback=([0-9]{1,3})){0,1}:\)\\s*$/e", "Keep('<:block>' . view_blog_digest('$2','$4','$6'),'L')"); /** * VIEW_BLOG_DIGEST - * * */ //function view_blog_digest($group, $start, $months) function view_blog_digest($group) { global $pagename; // Check for (:blogdigest:) with no GROUP if($group == '') { $pieces = explode('.', $pagename); $group = $pieces[0]; } $digest = get_raw_digest($group); $html = MarkupToHTML($pagename, $digest); return $html; } /* --------------- Archive --------------- */ // Handle the archive with a markup replacement: // // 1.0.3 - This will match (:blogarchive:), or (:blogarchive GROUP:), // with (:blogarchive GROUP[.\]PAGE:) for legacy support // // 1.1.0 - Removed [.\]PAGE support to simplify the regexp, added // months= and wrap=; GROUP now uses group= // // Regexp matches: // 0 -> full match // 1 -> group=GROUP // 2 -> GROUP // 3 -> months=AA // 4 -> AA // 5 -> wrap=B // 6 -> B // Markup('blogarchive', 'directives', "/^\(:blogarchive?(\s+group=($GroupPattern)){0,1}+(\s+monthsback=([0-9]{1,2})){0,1}+(\s+wrap=([0-9]{1})){0,1}:\)\\s*$/e", "view_blog_archive('$2','$4','$6')"); /** * VIEW_BLOG_ARCHIVE - Returns a graphical view of recent blog entries * * args: group to scan, months to show, wrapping * returns: string of html markup containing the graphical view * */ function view_blog_archive($group, $months, $wrap) { global $calendar_months_start, $calendar_months_number,$calendar_month_wrap; global $wikilog_home_page, $summary_only, $logdate, $PublishCalendarFmt; global $newest_first, $display_log_entries, $enable_publish, $pagename; // Check for a group parameter if($group == '') { $pieces = explode('.', $pagename); $group = $pieces[0]; } // Check for a month parameter $num_months = 0; if($months == '') { $num_months = $calendar_months_number; } else { $num_months = $months; } // Check for the wrap parameter $wrap_entries = 0; if($wrap == '') { $wrap_entries = $calendar_month_wrap; } else { $wrap_entries = $wrap; } // Something about date formatting $title = FmtPageName('$Name', $pagename); $startingdate = $logdate."16"; if(IsDate($startingdate)) { $year = substr($startingdate,0,4); $month= substr($startingdate,4,2); } else { if (IsDate($title)) { $year = substr($title,0,4); $month= substr($title,4,2); } else { $year = date("Y"); $month= date("m"); } } $startingtime = mktime(0,0,0,$month,16,$year); // generate the calendar navigation bar // TODO: add conditional here // TODO: this needs to be made aware of the number of months too // TODO: this doesn't even work right now (navigation) // $r = calendar_nav_bar($pagename,$startingtime,$num_months); // Start the calendar $r .= "\n"; $itime = $startingtime; $i = 0; $r_list = ''; // Build each month while($i < $num_months) { $r_mon = ""; $itime -= 2592000; $i++; // Check if we should wrap and start a new row if(($i % $wrap_entries) == 0) { $r_mon = $r_mon . ""; } // Append the month to the list $r_list .= $r_mon; } // Finish the calendar and return $r .= $r_list . "
"; // re-init the month string $r_mon .= calendar_month(strftime("%m",$itime),strftime("%Y",$itime), $group); $r_mon .= "
"; return $r; } /* --------------- Syndication --------------- */ /** * HANDLE_BLOG_RSS - Build an RSS 2.0 feed of a digest page. * * args: ??? * returns: XML string (RSS 2.0) * */ function HandleBlogRss($pagename, $auth='read') { global $RssMaxItems,$RssEditor, $RssDesc, $RssLink, $RssTitle, $RssLanguage, $RssCopyright, $RssEditor, $RssWebMaster, $RssChannelFmt, $RssChannelDesc, $RssItems,$RssItemFmt, $RssChannelBuildDate, $blogPermalinkStyle, $blogTimestampStyle, $HandleRssFmt,$FmtV,$ScriptUrl,$Group,$Name; // RSS 2.0 definitions SDV($RssChannelFmt, ' ' . $RssTitle . ' ' . $RssLink . ' ' . $RssDesc . ' ' . $RssLanguage . ' ' . $RssCopyright . ' ' . $RssEditor . ' ' . $RssWebMaster . ' $RssChannelBuildDate Kind-of Blog'); SDV($RssItemFmt,' $RssItemTitle $RssItemLink $RssItemPubDate $RssItemDesc '); SDV($HandleRssFmt, array(&$RssChannelFmt, &$RssItems, "\n \n ")); // Security -- don't try to build a feed for restricted pages $page = RetrieveAuthPage($pagename, $auth, false, READPAGE_CURRENT); if (!$page) Abort("?cannot read $pagename"); // Get the page and group $parts = explode('.', $pagename); $blog_group = $parts[0]; $blog_page = $parts[1]; // The timestamp for the RSS feed $cbgmt = $page['time']; SDV($RssChannelBuildDate, gmdate('D, d M Y H:i:s \G\M\T', $cbgmt)); // Get the raw digest for RSS transformation $source = get_raw_digest($blog_group); // Taken together, the regex parses the digest into: // match[0] = selection (entire string, not very useful) // match[1] = raw args // match[2] = entry $entryRegEx = "/\(:blogentry\s+(.*?):\)(.*?)(?=\(:blogentryend:\))/s"; $num_matches = preg_match_all($entryRegEx, $source, $match, PREG_SET_ORDER); // DEBUG: It's always helpful to see what your regex is: // print "

$entryRegEx

"; // print "
Found $num_matches matches " . $match[0][2] . "
"; // Go through each match and format the pieces for RSS for($i = 0; $i < $num_matches; $i++) { // Parse the raw arguments $args = ParseArgs($match[$i][1]); $title = $args['title']; $time = $args['time']; $link = $args['permalink']; $description = MarkupToHTML($pagename, ltrim(rtrim($match[$i][2]))); // Parse the permanent link for the pagename (numeric) only $cnt = preg_match('/.*?([0-9]{8})/', $link, $lm); $cnt = preg_match('/(.*?)\./', $pagename, $pm); $page = $lm[1]; $group = $pm[1]; $link = $ScriptUrl ."/". $group . "/" . $page; // Build the item's RSS tags $FmtV['$RssItemTitle'] = $title; $FmtV['$RssItemLink'] = $link; $FmtV['$RssItemDesc'] = $description; $FmtV['$RssItemAuthor'] = $RssEditor; // Use the timestamp and the pagename to get the time components // FIXME: this is really shaky, verify time is working properly $cnt = preg_match('/.*?([0-9]{2}):([0-9]{2}).*?/', $time, $rm); $hour = $rm[1]; $min = $rm[2]; $year = substr($page, 0, 4); $month = substr($page, 4, 2); $day = substr($page, 6, 2); $gmt = gmdate("r", mktime($hour, $min, 0, $month, $day, $year)); $FmtV['$RssItemPubDate'] = $gmt; // Encoding (optional) // $RssItems[] = entityencode(FmtPageName($RssItemFmt, $title)); $RssItems[] = FmtPageName($RssItemFmt, $title); } // Here is where the RSS feed is sent to the client header("Content-type: text/xml"); PrintFmt($pagename, $HandleRssFmt); } /* --------------- Miscellaneous Stuff --------------- */ // Allow page names to be all numerics. $PageNamePattern = "[0-9]{8}"; // process date links Markup('datelink','>inline', "/\[\[($GroupPattern(?:[\/.])$PageNamePattern)\|(.*?)\]\]/e", "Keep(MakeDateLink(\$pagename,'$1','$2'),'L')"); // bugfix - 1.0.3 - Fixed function call (londate -> longdate) Markup('daylink','>inline', "/\[\[((?:$GroupPattern\/)?($PageNamePattern))\]\]/e", "Keep(MakeDateLink(\$pagename,'$1',((IsDate('$2')) ? longdate('$2') : '$2')),'L')"); // // bugfix 1.1.1 - delayed execution to prevent links from being // processed as dates // SDV($DateSeparatorPattern,'[-.\/]'); Markup('wdate','block',"/(\d\d\d\d)($DateSeparatorPattern)(\d\d)\\2(\d\d)/e", "((IsDate('$1$3$4')) ? longdate('$1$3$4') : '$0')"); /* =============== UTILITY FUNCTIONS =============== */ // These functions support the high-level functions above, // for the most part, they are copied verbatim from my original // hack, and the original authors' code. /** * GET_RAW_DIGEST - Returns digest in wiki markup format * * args: group to scan * returns: string of wiki markup * */ function get_raw_digest($group) { global $calendar_months_number, $max_blog_entries; $digest = ""; $entries_found = 0; // Get the current time, then loop backward by month // looking for entries $itime = mktime(0, 0, 0, date('m'), 16, date('Y')); $i = 0; for($i = $calendar_months_number; $i > 0; $i--) { $month = strftime("%m", $itime); $year = strftime("%Y", $itime); // This decriments the time, I don't really know how $itime = $itime - 2592000; // Start at the last day of the month and work backward // looking for blog entries $j = 0; $prefix = $group . "/" . $year . $month; $last_day_of_month = strftime("%d", mktime(0, 0, 0, $month+1, 0, $year)); for($j = $last_day_of_month; $j > 0; $j--) { // Format the date a bit if ($j < 10) { $day ="0".$j; } else { $day=$j; } $entryname= $prefix . $day; // See if there is a blog entry for the current date, and, if so // pluck it out and append it to the list if(PageExists($entryname) && ($entries_found < $max_blog_entries)) { // Read the page content $snippet = ReadPage($entryname); $stuffing = $snippet['text']; // Count and match the individual entries // FIXME: globalize this pattern $entryRegEx = "/\(:blogentry\s+(.*?):\)(.*?)(?=\(:blogentryend:\))/s"; $num_matches = preg_match_all($entryRegEx, $stuffing, $match, PREG_SET_ORDER); for($k = 0; $k < $num_matches; $k++) { if($entries_found < $max_blog_entries) { $digest .= $match[$k][0] . "(:blogentryend:)\n\n"; $entries_found++; } } // We want a dividing line between entries. But we don't want one // after the last entry, and we don't want a hanging divider if we can't // find max_entries. So I figure we can safely add a divider after we've // at least one entry // if($entries_found > 0) { // $digest .= "\n----\n"; // } // $entries_found++; // $digest .= $stuffing; } } } return $digest; } /* --------------- ... --------------- */ function home_link($wikiloghome) { global $WikilogHomeText, $HTMLVSpace; $WikilogHomeLink= ($WikilogHomeText=='') ? "[[$wikiloghome]]" : "[[$wikiloghome | $WikilogHomeText]]"; return "$HTMLVSpace

$WikilogHomeLink:

"; } function calendar_month($month,$year,$group) { global $pagename, $monthnames, $shortdaynames, $calendar_weekstyle; $prefix = $group . "/" . $year . $month; $todays_time=mktime(0,0,0,date("m"),date("d"),date("Y")); $last_day_of_month=strftime("%d",mktime(0,0,0,$month+1,0,$year)); $r=""; // header with month and year // TODO: monthly link to digest here $my_date = $year . ($month - 1); // $r.=""; $r.=""; // weekday names $r.=""; for ($i=$calendar_weekstyle;$i<7+$calendar_weekstyle;$i++) { $r.=""; } $r.=""; $count=0; // pre-padding $r.=""; for ($i=0;$i<(strftime("%w",mktime(0,0,0,$month,1,$year))-$calendar_weekstyle+7)%7;$i++) { $r.=""; $count++; } // days for ($i=1;$i<=$last_day_of_month;$i++) { if ($count%7==0 && $count>0) $r.=""; if ($i<10) { $day="0".$i; } else { $day=$i; } $entryname= $prefix . $day; $r.=""; $count++; } // post-padding while ($count%7!=0) { $r.=""; $count++; } return $r."
". $monthnames[$month-1] . " ". $year . "" . $monthnames[$month-1] . " ". $year . "
" . $shortdaynames[$i] . "
 
[[". $entryname . "|" . $day . "]]"; } else { $r.="noentry'>[[". $entryname . "|" . $day . "]]"; } $r.=" 
\n"; } function SetBlogTitle($text) { global $DefaultBlogTitle; return ($text=='') ? $DefaultBlogTitle : $text; } function IsDate($title) { if (is_numeric($title) && strlen($title) == 8) { $year = substr($title,0,4); $month= substr($title,4,2); $day = substr($title,6,2); return checkdate($month, $day, $year); } else { return false; } } function longdate($title) { global $calendar_datestyle, $monthnames, $longdaynames; $year = substr($title,0,4); $month= substr($title,4,2); $day = substr($title,6,2); if ($day[0] == "0") { $day = $day[1]; } $longmonth = $monthnames[$month-1]; $r = ($calendar_datestyle == 0) ? ", $longmonth $day, " : ", $day $longmonth "; $dayname=$longdaynames[strftime("%w",mktime(0,0,0,$month,$day,$year))]; return "$dayname$r$year"; } function calendar_nav_bar($pagename,$startingtime,$months) { // global $calendar_months_number; $calendar_months_number = $months; $currentmonth= date("Y") . date("m"); $lasttime =$startingtime-$calendar_months_number*2592000; $lastmonth= strftime("%Y",$lasttime) . strftime("%m",$lasttime); $nexttime =$startingtime+$calendar_months_number*2592000; $nextmonth=strftime("%Y",$nexttime) . strftime("%m",$nexttime); $r = "

« "; if ($currentmonth < $lastmonth) $r.=calendar_nav($pagename,$currentmonth,true) . " · "; $r.=calendar_nav($pagename,$lastmonth,false) . " · " . calendar_nav($pagename,$nextmonth,false); if ($currentmonth > $nextmonth) $r.=" · " . calendar_nav($pagename,$currentmonth,true); return $r . " »

\n"; } function calendar_nav($pagename,$yearmo,$highlight) { global $calendar_months_number, $monthnames, $period, $url_connector; $year = substr($yearmo,0,4); $r = "[[$pagename$url_connector"."logdate=$yearmo | "; $mname = $monthnames[substr($yearmo,4,2)-1] . " " . $year; if ($calendar_months_number == 1) $mname .= " " . $period; if ($highlight) $mname = highlight($mname); return "$r$mname]]"; } function highlight($text) { return "$text"; } function shortdate($year, $month, $day) { global $calendar_datestyle; switch ($calendar_datestyle) { case 0: return "$month/$day/$year"; case 1: return "$day.$month.$year"; case 2: return "$year–$month–$day"; } } function show_date($page) { global $default_date_text; $title = FmtPageName('$Name',$page); return (IsDate($title)) ? "$default_date_text: ".longdate($title) : $default_date_text; } function MakeDateLink($pagename,$ref,$btext) { global $LinkPageCreateFmt,$day_as_wiki; $WikiDateCreateFmt = "\$LinkText"; if ($day_as_wiki==true) return MakeLink($pagename,$ref,$btext); $hold = $LinkPageCreateFmt; $LinkPageCreateFmt = $WikiDateCreateFmt; $r = MakeLink($pagename,$ref,$btext); $LinkPageCreateFmt = $hold; return $r; } function select_calendar_date($pagename) { global $calendar_months_start, $calendar_months_number,$calendar_month_wrap; global $logdate; // start configured number of months before/ahead $startingdate = $logdate."16"; if (IsDate($startingdate)) { $year = substr($startingdate,0,4); $month= substr($startingdate,4,2); } else { $year = date("Y"); $month= date("m"); } $startingtime = mktime(0,0,0,$month,16,$year); // generate the calendar $r=""; $itime=$startingtime; $i=0; while ($i<$calendar_months_number) { $r.=calendar_days(strftime("%m",$itime),strftime("%Y",$itime)); // +1 month // It's actually 30 days which could break if displaying a lot of months // but it should be ok when displaying only one or two years at a time $itime=$itime+2592000; $i++; } return $r; } function calendar_days($month,$year) { global $SpaceDateString; $todays_time=mktime(0,0,0,date("m"),date("d"),date("Y")); $last_day_of_month=strftime("%d",mktime(0,0,0,$month+1,0,$year)); $r=''; // days for ($i=1;$i<=$last_day_of_month;$i++) { if ($i<10) { $day="0".$i; } else { $day=$i; } $entry= "$year$SpaceDateString$month$SpaceDateString$day"; $s = (abs($todays_time - mktime(0,0,0,$month,$i,$year)) < 86400) ? " selected='selected'" : ''; $r.=""; } return $r; }