Extension:SpecialCalendar

The goal
The goal is to have (edit an view) a calendar on Mediawiki that ca be download at the iCal format.

Install
$wgICalenarVersion = '2.0'; $wgICalenarPerodID = '-//Fabricants de Joie//NONSGML mediawiki//FR'; $wgICalenarDefaultPage = 'Calendar';
 * copy the source on a file named SpecialCalendar.php.
 * copy this file in the extensions directory.
 * add include_once('extensions/SpecialCalendar.php'); in the LocalSettings.php file.
 * in the LocalSettings.php file define for example

How to use
  introductions === Event1 ===    comments === Event2 ===    comments
 * to follow the example edit the page Mediawiki:Calendar and put :
 * Go to Special:Calendar to view the result (Special:Calendar/Calendar if it isn't the $wgICalenarDefaultPage calendar).
 * Remarque : the introduction and comments doesn't be in the iCal file !

Licence
GNU General Public License (GPL)

Author: user:sbrunner

Code
<?php if (!defined('MEDIAWIKI')) die; /* * 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. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * @author sbrunner * */

$wgExtensionCredits['specialpage'][] = array(   'name' => 'SpecialICalendar',    'url' => 'http://www.mediawiki.org/wiki/Extension:SpecialICalendar',    'author' => 'Stéphane Brunner' );

$wgExtensionFunctions[] = "wfiCalExtension";

require_once( "$IP/includes/SpecialPage.php" );

function wfiCalExtension { global $IP, $wgMessageCache, $myForm, $wgICalenarDefaultPage;

$wgMessageCache->addMessages(array('calendar' => 'Calendar')); $wgMessageCache->addMessages(array('calendardate' => ' From $1 to $2')); //	$wgMessageCache->addMessages(array('calendardateformat' => 'D j M Y G:i:s')); $wgMessageCache->addMessages(array('calendardateformat' => 'l j F Y')); //	$wgMessageCache->addMessages(array('calendardateformat' => '%A %d %B %Y %H:%M')); $wgMessageCache->addMessages(array('calendardownload' => 'Gets the calendar as iCal format. '));

$wgMessageCache->addMessages(array('mon' => 'Mon')); $wgMessageCache->addMessages(array('tue' => 'Tue')); $wgMessageCache->addMessages(array('wed' => 'Wed')); $wgMessageCache->addMessages(array('thu' => 'Thu')); $wgMessageCache->addMessages(array('fri' => 'Fri')); $wgMessageCache->addMessages(array('sat' => 'Sat')); $wgMessageCache->addMessages(array('sun' => 'Sun'));

if (isset($wgICalenarDefaultPage)) { $wgMessageCache->addMessages(array($wgICalenarDefaultPage => '=== Event ===  ')); }

SpecialPage::addPage( new iCalSpecialPage ); }

class iCalSpecialPage extends SpecialPage {

// Day and mounth to display var $langueDate = array; var $dateformat;

function iCalSpecialPage { SpecialPage::SpecialPage( 'Calendar' );

$this->dateformat = wfMsg('calendardateformat');

$this->langueDate['Mon'] = wfMsg('mon'); $this->langueDate['Tue'] = wfMsg('tue'); $this->langueDate['Wed'] = wfMsg('wed'); $this->langueDate['Thu'] = wfMsg('thu'); $this->langueDate['Fri'] = wfMsg('fri'); $this->langueDate['Sat'] = wfMsg('sat'); $this->langueDate['Sun'] = wfMsg('sun'); $this->langueDate['Monday'] = wfMsg('monday'); $this->langueDate['Tuesday'] = wfMsg('tuesday'); $this->langueDate['Wednesday'] = wfMsg('wednesday'); $this->langueDate['Thursday'] = wfMsg('thursday'); $this->langueDate['Friday'] = wfMsg('friday'); $this->langueDate['Saturday'] = wfMsg('saturday'); $this->langueDate['Sunday'] = wfMsg('sunday'); $this->langueDate['Jan'] = wfMsg('jan'); $this->langueDate['Feb'] = wfMsg('feb'); $this->langueDate['Mar'] = wfMsg('mar'); $this->langueDate['Apr'] = wfMsg('apr'); $this->langueDate['May'] = wfMsg('may'); $this->langueDate['Jun'] = wfMsg('jun'); $this->langueDate['Jul'] = wfMsg('jul'); $this->langueDate['Aug'] = wfMsg('aug'); $this->langueDate['Sep'] = wfMsg('sep'); $this->langueDate['Oct'] = wfMsg('oct'); $this->langueDate['Nov'] = wfMsg('nov'); $this->langueDate['Dec'] = wfMsg('dec'); $this->langueDate['January'] = wfMsg('january'); $this->langueDate['February'] = wfMsg('february'); $this->langueDate['March'] = wfMsg('march'); $this->langueDate['April'] = wfMsg('april'); $this->langueDate['May'] = wfMsg('may'); $this->langueDate['June'] = wfMsg('june'); $this->langueDate['July'] = wfMsg('july'); $this->langueDate['August'] = wfMsg('august'); $this->langueDate['September'] = wfMsg('septembre'); $this->langueDate['October'] = wfMsg('octobre'); $this->langueDate['November'] = wfMsg('novembre'); $this->langueDate['December'] = wfMsg('decembre'); }

function execute( $par ) { global $wgRequest, $wgOut, $wgUser, $wgICalenarVersion, $wgICalenarPerodID, $wgICalenarDefaultPage, $wgTitle, $wgInputEncoding;

$this->setHeaders;

if ( $this->userCanExecute( $wgUser ) ) { $action = $wgRequest->getVal( 'action' ); $cal = isset($par) ? $par : $wgRequest->getVal( 'cal' ); if ($cal == null) { $cal = $wgICalenarDefaultPage; }			$text = wfMsg($cal); if ( "raw" == $action ) { $wgOut->disable; header( 'Content-type: text/calendar; charset='.$wgInputEncoding );

echo 'BEGIN:VCALENDAR'."\n"; echo 'VERSION:'.$wgICalenarVersion."\n";//'2.0'; echo 'PRODID:'.$wgICalenarPerodID."\n"; //'-//Fabricants de Joie//NONSGML mediawiki//FR'; $this->parce('doical', $text."\n", $cal); echo 'END:VCALENDAR'."\n"; }			else { $titleObj = Title::makeTitle( NS_SPECIAL, "Calendar" ); $action = $titleObj->escapeLocalURL( "cal=".urlencode( $cal ) ); $wgOut->addHTML(wfMsg('calendardownload', $titleObj->escapeLocalURL( "cal=".urlencode( $cal ).'&action=raw' )));

$titleObj = Title::makeTitle( NS_MEDIAWIKI, $cal ); $action = $titleObj->escapeLocalURL( "action=edit" ); $wgOut->addHTML(' ['.wfMsg('editsection').'] ');

$index = strpos($text, '', $index); }				if ($end !== false) { $wgOut->setPagetitle(substr($text, $index, $end - $index)); $text = substr($text, $end +1); }

$index = strpos($text, '<dateformat|'); $end = false; if ($index !== false) { $index = $index + 12; $end = strpos($text, '>', $index); }				if ($end !== false) { $this->dateformat = substr($text, $index, $end - $index); $text = substr($text, $end +1); }

$this->parce('dodisplay', $text, $cal); }		} else { $this->displayRestrictionError; }	}

function parce($func, $text, $cal) { global $wgOut;

$oldindex = 0; $index = strpos($text, '==='); while ($index !== false) { if ($func == 'dodisplay' && $oldindex < $index) { $wgOut->addWikiText(substr($text, $oldindex, $index - $oldindex)); }			$index = $index + 3; $end = strpos($text, '===', $index); $title = null; $startDate = null; $endDate = null; $categories = null; if ($end !== false) { $title = substr($text, $index, $end - $index); $index = strpos($text, '<start|', $end); if ($index !== false) { $index = $index + 7; $end = strpos($text, '>', $index); if ($end !== false) { $startDate = substr($text, $index, $end - $index); }				}			}			if ($end !== false) { $index = strpos($text, '<end|', $end); if ($index !== false) { $index = $index + 5; $end = strpos($text, '>', $index); if ($end !== false) { $endDate = substr($text, $index, $end - $index); }				}				else { $end = false; }			}			if ($end !== false) { $index = strpos($text, '===', $end);

if ($end !== false) { $cindex = strpos($text, '<categories|', $end); if ($cindex !== false && ($index == false || $cindex < $index)) { $cindex = $cindex + 12; $end = strpos($text, '>', $cindex); if ($end !== false) { $categories = substr($text, $cindex, $end - $cindex); }					}				}				$oldindex = $end + 1; $titleObj = Title::makeTitle( NS_SPECIAL, "Calendar/".$cal ); $this->$func($title, $categories, $titleObj->escapeFullURL.'#'.str_replace('%', '.', urlencode(str_replace(' ', '_', $title))), $startDate, $endDate); }			else { $index = -1; }		}		if ($func == 'dodisplay' && $oldindex < strlen($text)) { $wgOut->addWikiText(substr($text, $oldindex)); }	}

function doical($title, $categories, $url, $startDate, $endDate) { if (strlen($startDate) == 16 && strlen($endDate) == 16) { echo 'BEGIN:VEVENT'."\n"; $sts = $this->getdate($startDate); echo 'DTSTART:'.gmdate('Ymd', $sts).'T'.gmdate('His', $sts)."Z\n";//19970714T170000Z; $ets = $this->getdate($endDate); echo 'DTEND:'.gmdate('Ymd', $ets).'T'.gmdate('His', $ets)."Z\n"; echo 'SUMMARY:'.$title."\n"; echo 'URL:'.$url."\n"; if ($categories != null) { echo 'CATEGORIES:'.$categories."\n"; }			echo 'END:VEVENT'."\n"; }	}	function dodisplay($title, $categories, $url, $startDate, $endDate) { global $wgOut;

$wgOut->addHTML('<div class="'.$categories.'">'); // TODO multi ! $wgOut->addWikiText('=== '.$title.' ==='); if (strlen($startDate) == 16 && strlen($endDate) == 16) { $wgOut->addWikiText(wfMsg('calendardate', strtr(date($this->dateformat, $this->getdate($startDate)), $this->langueDate), strtr(date($this->dateformat, $this->getdate($endDate)), $this->langueDate))); }		else { $wgOut->addWikiText('parce error'); }		$wgOut->addHTML(' '); }	function getdate($date) { $result = mktime(substr($date, 9, 2), substr($date, 11, 2), substr($date, 13, 2), substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4)); return $result; } } ?>