Extension:LifeMarks/LifeMarks.php

From MediaWiki.org
Jump to: navigation, search

[edit] Source Code

The following should be placed into a file named LifeMarks.php in your /extensions directory.

NOTE
This code does not work in recent MW versions. Please see the discussion page for code that works.
<?php
/*
 LifeMarks MediaWiki extension
 
SQL:
 
The following SQL must be executed prior to running this extension.  Please note that this extension does not yet
support database prefixes.
 
CREATE TABLE lifemarks (
    lmid MEDIUMINT(9) AUTO_INCREMENT NOT NULL PRIMARY KEY,
    page_id INT(8) UNSIGNED NOT NULL DEFAULT 0,
    year INT(4) UNSIGNED NOT NULL DEFAULT 0,
    month INT(2) UNSIGNED NOT NULL DEFAULT 0,
    day INT(2) UNSIGNED NOT NULL DEFAULT 0,
    description MEDIUMTEXT NOT NULL,
    tags MEDIUMTEXT NOT NULL
);
 
 
 
The purpose of this extension is to log lifemarks throughout a Wiki for collection and display.
A LifeMark is essentially an event in a life, or mark on a timeline, important enough for note.
 
USAGE:
 
You can simply call the tag with a date and a description:
 <lifemark>1998-12-31: Party like it's 1999</lifemark>
 
The above example produces no output and can be used easily inline text:
 
It wasn't until the the server crashed <lifemark>2003-5-12: Server crashed with all data</lifemark> that 
we decided to invest in a backup solution that was more reliable.
 
Lifemarks can be told to display themselves with either keywords or variables based on PHP Date() format:
<lifemark display="event">1999-12-31: Y2K Event</lifemark>
    produces (with wikimarkup): '''1999-12-31''': Y2K Event
<lifemark display="'''%F %j, %Y''': %description%">1999-12-31: Y2K Event</lifemark>
    produces:  '''December 31, 1999''': Y2K Event
Keywords are as follows (as applied to the above example):
    event:    '''1999-12-31''': Y2K Event
 
Lifemarks can also be tagged by text for categories:
<lifemark tag="Parties">2003-12-25: 2003 Company Christmas Party</lifemark>
 
Finally, multiple lifemarks can be tagged within a single block (tags and display styles apply to all):
<lifemark tag="Parties" display="event">
 1999-12-25: 1999 Company Christmas Party
 2001-04-30: Bob's 30th birthday party
 2003-07-04: Angela's [[Fourth of July] bash
 2005-02-14: Tina hosts her [[Valentine's Day|Valentine]] bash
</lifemark>
 
Also illustrated above is that wiki markup and links can be used in the descriptions.
 
TODONOW: Prevent duplicates, possibly low-level maint on special page
 
TODONOW: explain: Why not use timestamps?  Ambiguous dates!  QDateStamps!  Something!
 
-------------------------------------------------
CHANGELOG:
0.2.0: Changed hardcoded month name strings to {{int:MonthName}} to support internationalization
0.1.0: Initial Release
 
 
*/
 
$extensionname = '[http://meta.wikimedia.org/wiki/LifeMarks LifeMarks]';
$extensiondesc = 'LifeMarks are notable events in a timeline with a description, (approximate) date and tags';
$extensionauthor = '[[w:User:Bakerq|Quentin Baker]]';
$extensionversion = '0.1.0';
if (!defined('MEDIAWIKI')) die();
$wgExtensionFunctions[] = 'wfLifeMarksExtension';
$wgHooks['ArticleSaveComplete'][] = 'saveLifeMarks';
$wgExtensionCredits['parserhook'][] = array(
        'name' => $extensionname,
        'description' => $extensiondesc,
        'author' => $extensionauthor,
        'version' => $extensionversion
);
$wgExtensionFunctions[] = 'wfSpecialLifeMarks' ;
$wgExtensionCredits['specialpage'][] = array(
        'name' => $extensionname,
        'description' => 'A Special Page for listing all LifeMarks on a wiki and organizing them',
        'author' => $extensionauthor,
        'version' => $extensionversion
);
 
//GLOBAL EXTENSION VARIABLES - THESE SHOULD BE SET IN LocalSettings.php
$wgLifeMarkDBPrefix = $wgLifeMarkDBPrefix ? $wgLifeMarkDBPrefix : null;
$wgLifeMarkDefaultDisplay = $wgLifeMarkDefaultDisplay ? $wgLifeMarkDefaultDisplay : "none";
$wgLifeMarkDefaultListDisplay = $wgLifeMarkDefaultListDisplay ? $wgLifeMarkDefaultListDisplay : "events";
$wgLifeMarkDefaultOrderBy = $wgLifemarkDefaultOrderBy ? $wgLifeMarkDefaultOrderBy : 'year ASC, month ASC, day ASC, description ASC';
 
function wfLifeMarksExtension() {
    global $wgParser;
    $wgParser->setHook( "lifemark", "renderLifeMarks" );
    $wgParser->setHook( "lifemarks", "renderLifeMarks" );
    $wgParser->setHook( "lifemarklist", "renderLifeMarksList" );
    $wgParser->setHook( "lifemarkslist", "renderLifeMarksList" );
}
 
function renderLifeMarks( $input, $argv) {
    global $wgLifeMarkDefaultDisplay;
    // COLLECT PARAMETERS
    $tagstext = $argv["tags"];
    $disptext = $argv["display"];
    # displaytemplate is grabbed from wgLifeMarkDefaultDispay first, then overwritten by disp parameter
    if (isset($disptext)) { 
        $displaytemplate = $disptext;
    } else {
        $displaytemplate = $wgLifeMarkDefaultDisplay;
    }
    # tags are collected from the parameter "tags"
    $tagstext = $argv["tags"];
 
    $foundlifemarks = getLifeMarks($input,$tagstext);
 
    //render, rinse, repeat
    $output = "";
    if ($foundlifemarks) {
        foreach($foundlifemarks as $lm)
            $output.=formatLifeMark($displaytemplate,$lm["year"],$lm["month"],$lm["day"],$lm["description"]);
        return($output);
    } else {
        // no lifemarks found
        return;
    }
}
 
 
 
 
function getLifeMarks($input,$tagstext) {
    // GET INFO FROM BODY OF TAG
    # now search the body for lifemark events (this code based on code from the Events extension)
    $bodymarks = preg_split("/[\n\r]+/", $input);
    foreach ($bodymarks as $lifemark_bodyline) {
    $exp = '/^\s*([0-9]{4}-[0-9]{1,2}-[0-9]{1,2}):\s*(.+)$/';
        if (preg_match($exp,$lifemark_bodyline,$matches)) {
            $date = $matches[1];
            $description = $matches[2];
            $datebits = explode("-",$date);
            $date_year  = $datebits[0];
            $date_month = $datebits[1];
            $date_day   = $datebits[2];
            $foundmarks[] = array(
                'year'    => $date_year,
                'month'    => $date_month,
                'day'    => $date_day,
                'description' => $description,
                'tags' => $tagstext
            );
        }
    }
    return($foundmarks);
}
 
 
 
# GRATEFULLY BORROWED FROM TASKS EXTENSION
function saveLifeMarks( $article, $user, $text ) {
    global $wgLifeMarkDBPrefix;
        $lifemarks_buffer = null;
        $page_id = $article->getID();
        $dbr =& wfGetDB( DB_MASTER );
        # Delete all tasks for this page.
        $dbr->delete(
                $wgLifeMarkDBPrefix . 'lifemarks',
                array( 'page_id' => $page_id )
        );
        $matches = array();
        $elements = array('lifemarks', 'lifemark');
        $text = Parser::extractTagsAndParams( $elements, $text, $matches );
        foreach( $matches as $marker => $data ) {
                list( $element, $content, $params, $tag ) = $data;
                $found = getLifeMarks($content,$params["tags"]);
                foreach($found as $datum)
                    $lifemarks_buffer[] = $datum;
        }
        # Re-insert all lifemarks that were created when parsing this page.
        foreach ($lifemarks_buffer as $lm) {
                $lm['page_id'] = $page_id;
                $dbr->insert(
                    $wgLifeMarkDBPrefix.'lifemarks',
                    $lm
                );
        }
        return 1;
}
 
 
function formatLifeMark($displaytemplate, $year, $month, $day, $desc, 
            $tags=null, $source=null, $parse_wiki=true) {
    global $wgLifeMarkDefaultDisplay, $wgTitle, $wgOut;
 
    // let's create some numerics
    $year = intval($year);
    $month = intval($month);
    $day = intval($day);
 
    // Process display keywords into something we can use
    switch ($displaytemplate) {
        case "date" :       $displaytemplate = "%F% %j%%S%, %Y%"; break;  
        case "slashdate" :  $displaytemplate = "%m%/%d%/%y%"; break;  
        case "dashdate" :   $displaytemplate = "%m%-%d%-%y%"; break;  
        case "longdate" :   $displaytemplate = "%F% %j%%S%, %Y%"; break;  
        case "meddate" :    $displaytemplate = "%M% %j%, %Y%"; break;  
        case "event" :      $displaytemplate = "'''%m%-%d%-%Y%''': %source% %description%"; break;
        case "events" :     $displaytemplate = "'''%m%-%d%-%Y%''': %source% %description%<br />"; break;
        case "longevent" :  $displaytemplate = "'''%F% %j%%S%, %Y%''': %source% %description%"; break;
        case "longevents":  $displaytemplate = "'''%F% %j%%S%, %Y%''': %source% %description%<br />"; break;
        case "medevent" :   $displaytemplate = "'''%M% %j%, %Y%''': %source% %description%"; break;
        case "medevents" :  $displaytemplate = "'''%M% %j%, %Y%''': %source% %description%<br />"; break;
        case "slashevent" : $displaytemplate = "'''%m%/%d%/%y%''': %source% %description%"; break;
        case "slashevents": $displaytemplate = "'''%m%/%d%/%y%''': %source% %description%<br />"; break;
        case "dashevent" :  $displaytemplate = "'''%m%-%d%-%y%''': %source% %description%"; break;
        case "dashevents":  $displaytemplate = "'''%m%-%d%-%y%''': %source% %description%<br />"; break;
        case "image" :      $displaytemplate = "IMG"; break;  //TODO: allow an image with a title tag, like a pin
        case "none" :       $displaytemplate = ""; break;
    }
 
    $localParser = new Parser();
    $output = "";
    $thisline = $displaytemplate;
    # simplestuff
    $thisline = str_replace("%year%", "%Y%", $thisline);  // convert big friendly names to stuff we use below
    $thisline = str_replace("%month%", "%m%", $thisline);
    $thisline = str_replace("%day%", "%d%", $thisline);
    $thisline = str_replace("%description%", $desc, $thisline);
    $thisline = str_replace("%source%", $source, $thisline);
    # TOUGH STUFF:    (see the big commented block below - I was planning to use date() for all this, but well...
    $thisline = str_replace("%d%", ((strlen(strval($day))<2) ? ("0".$day) : ($day)), $thisline); // make $day 2 digits
    $thisline = str_replace("%m%", ((strlen(strval($month))<2) ? ("0".$month) : ($month)), $thisline); // 2digit month
    $thisline = str_replace("%y%", ((strlen(strval($year))>2) ? (substr($year,-2,2)) : ($year)), $thisline); // 2digit year
    $thisline = str_replace("%j%", $day, $thisline); //day, no leading zeros
    $thisline = str_replace("%n%", $month, $thisline); //month, no leading zeros
    $thisline = str_replace("%Y%", $year, $thisline);  //year 4 digits
    $monthname[1]  = array( 's'=>'{{int:Jan}}', 'l' => '{{int:January}}' );
    $monthname[2]  = array( 's'=>'{{int:Feb}}', 'l' => '{{int:February}}' );
    $monthname[3]  = array( 's'=>'{{int:Mar}}', 'l' => '{{int:March}}' );
    $monthname[4]  = array( 's'=>'{{int:Apr}}', 'l' => '{{int:April}}' );
    $monthname[5]  = array( 's'=>'{{int:May}}', 'l' => '{{int:May}}' );
    $monthname[6]  = array( 's'=>'{{int:Jun}}', 'l' => '{{int:June}}' );
    $monthname[7]  = array( 's'=>'{{int:Jul}}', 'l' => '{{int:July}}' );
    $monthname[8]  = array( 's'=>'{{int:Aug}}', 'l' => '{{int:August}}' );
    $monthname[9]  = array( 's'=>'{{int:Sep}}', 'l' => '{{int:September}}' );
    $monthname[10] = array( 's'=>'{{int:Oct}}', 'l' => '{{int:October}}' );
    $monthname[11] = array( 's'=>'{{int:Nov}}', 'l' => '{{int:November}}' );
    $monthname[12] = array( 's'=>'{{int:Dec}}', 'l' => '{{int:December}}' );
    $thisline = str_replace("%F%", $monthname[$month]['l'], $thisline); //long month name
    $thisline = str_replace("%M%", $monthname[$month]['s'], $thisline); //short month name
    switch (substr($day,-1,1)) {
        case "1" : $thisline = str_replace("%S%", "st", $thisline); break;
        case "2" : $thisline = str_replace("%S%", "nd", $thisline); break;
        case "3" : $thisline = str_replace("%S%", "rd", $thisline); break;
        default  : $thisline = str_replace("%S%", "th", $thisline); break;
    }
    $thisline = str_replace("%y", $year, $thisline);
 
    $processedline = $thisline;
    if ($parse_wiki) {  // IF THIS IS GOING TO BE PUT IN A  WIKI TABLE, DON'T PARSE NOW, THAT WILL COME LATER
        $temp_output = $localParser->parse($processedline, $wgTitle, $wgOut->mParserOptions, false);
        $output = $temp_output->getText();
    } else {
        $output = $processedline;
    }
    return($output);
}
 
 
 
 
function renderLifeMarksList( $input, $argv) {
    global $wgOut, $wgTitle, $wgParser, $wgLifeMarkDefaultOrderBy, $wgLifeMarkDefaultListDisplay,$wgLifeMarkDBPrefix;
    $page_titles = array();
    $dbr =& wfGetDB( DB_MASTER );
    // COLLECT FILTER PARAMETERS
    $yeartext = $argv["year"];
    $monthtext = $argv["month"];
    $daytext = $argv["day"];
    $tagtext = $argv["tags"];
    $disptext = $argv["display"];
    $formattext = $argv["format"];
    $limittext = $argv["limit"];
    $offsettext = $argv["offset"];
    $pagetext = $argv["page"];  
    // DISPLAY PARAMETERS
    $orderbytext = $argv["orderby"]; 
    $sourcelinktext = $argv["sourcelinktext"];
    // COLLECT HEADER PARAM (should only be called from Special Page)
    $headertext = $argv["header"];  // this will be filled by the Special page and *should* mirror the orderbytext
    // COLLECT TABLE PARAMS
    $tabledefstext = $argv["tabledefs"];
    $bordertext = $argv["border"];
    $cellpaddingtext = $argv["cellpadding"];
    $cellspacingtext = $argv["cellspacing"];
    $styletext = $argv["style"];
    $classtext = $argv["class"];
 
    #Set up SQL options
    $defaultorderby = $wgLifeMarkDefaultOrderBy;
    $orderby = null;
    switch ($orderbytext) {
        case 'year' :   $orderby = "year ASC"; break;
        case '!year' :  $orderby = "year DESC"; break;
        case 'month' :  $orderby = "month ASC"; break;
        case '!month' : $orderby = "month DESC"; break;
        case 'day' :    $orderby = "day ASC"; break;
        case '!day' :   $orderby = "day DESC"; break;
        case 'desc' :   $orderby = "description ASC"; break;
        case '!desc' :  $orderby = "description DESC"; break;
        case 'tags' :   $orderby = "tags ASC"; break;
        case '!tags' :  $orderby = "tags DESC"; break;
        case 'page' :   $orderby = "page_id ASC"; break;
        case '!page' :  $orderby = "page_id DESC"; break;
        default :       if ($orderbytext) { $orderbytext.=", "; } 
                        // if it doesn't match any of the others, try straight SQL
                        $orderby = $orderbytext . " $defaultorderby";
    }
    $options = array( 'ORDER BY'=>$orderby );  //default order
 
    if ($limittext) {
        if ($offsettext) { $limittext = "$offsettext, $limittext"; }
        $options['LIMIT'] = $limittext;
    }
 
    # create the WHERE clause
    $where = array();
    if ($yeartext) {  //did they provide a year filter?
        if (preg_match('/([0-9]{4})-([0-9]{4})/',$yeartext,$matches)) {
            $year1 = $matches[1];
            $year2 = $matches[2];
            if ($year2<$year1) { list($year1,$year2) = array($year2,$year1);  } //swap 'em!
            $where[] = 'year>="' . $year1 .'"'; // the lower year
            $where[] = 'year<="' . $year2 .'"'; // the higher year
            // TODO: This entire extension completely ignores any years set for BC.
        } else {
            $where[] = 'year="' . $yeartext.'"'; 
        }
    }
    if ($monthtext) { // how about a month filter?
        if (preg_match('/([0-9]{1,2})-([0-9]{1,2})/',$monthtext,$matches)) {
            $month1 = $matches[1];
            $month2 = $matches[2];
            if ($month2<$month1) { list($month1,$month2) = array($month2,$month1);  } //swap 'em!
            $where[] = 'month>="' . $month1 .'"'; // the lower month
            $where[] = 'month<="' . $month2 .'"'; // the higher month
        } else {
            $where[] = 'month="' . $monthtext.'"'; 
        }
    }
    if ($daytext) { // perhaps a day filter?
        if (preg_match('/([0-9]{1,2})-([0-9]{1,2})/',$daytext,$matches)) {
            $day1 = $matches[1];
            $day2 = $matches[2];
            if ($day2<$day1) { list($day1,$day2) = array($day2,$day1);  } //swap 'em!
            $where[] = 'day>="' . $day1 .'"'; // the lower day
            $where[] = 'day<="' . $day2 .'"'; // the higher day
        } else {
            $where[] = 'day="' . $daytext . '"'; 
        }
    }
    if ($tagtext) { // this is a short tag filter
        $where[] = 'tags like "%' . $tagtext . '%"';    
    }
    if ($pagetext) { // and finally, a page_id filter
        if ($pagetext=="current") { //page="current" means list only marks on this page.
            $pageid = $wgTitle->getArticleID();
            $where[] = 'page_id="' . $pageid . '"';
        } elseif (is_numeric($pagetext)) {
            $where[] = 'page_id="' . $pagetext . '"';
        } else { # it's neither  the word "current" nor a numeric page_id, it must be the title
            //TODO:set up a way to take a page title and convert it to pageid.
            // I have yet to find a standard method of determining the pageid of an article by title string
        }
    }
    #set up a few display and count variables
    $sourcetag = "src";  //set up default sourcetag
    if ($sourcelinktext=="none") {
        $sourcetag = null;
    } else {
        if ($sourcelinktext) $sourcetag = $sourcelinktext;
    }
    $count = 0;
    $title = $input;
    # put together the output table definitions
    # THE POINT HERE IS TO SET UP A STRING VARIABLE CALLED $outputshell WHICH CONTAINS
    #  THE TEXT "%%CONTENT%%".  THIS TAGWILL BE REPLACED BY THE LIST OF FORMATTED LIFEMARKS
    $tabledefs = "$tabledefstext";
    if ($bordertext) $tabledefs.=" border=\"$bordertext\"";
    if ($cellpaddingtext) $tabledefs.=" cellpadding=\"$cellpaddingtext\"";
    if ($cellspacingtext) $tabledefs.=" cellspacing=\"$cellspacingtext\"";
    if ($styletext) $tabledefs.=" style=\"$styletext\"";
    if ($classtext) $tabledefs.=" class=\"$classtext\"";
 
    #do we want a list or a table?  First check the $format variable.  Failing that, check for any $tabledefs
    #if there are no tabledefs, then just return a list.  Otherwise, wrap it in a table.
    $tablemode = false;  // by default assume that just a list is wanted to be returned    
    if ($formattext=="list") {
        $tablemode = false;
    } elseif (($formattext=="table") or ($tabledefs)) {
        $tablemode = true;
    }
 
    # let's make the table look pretty
    if ($tablemode) {
        if ($title) { $tabletitle = "\n! align=\"center\" colspan=\"3\" | $input"; }
        if ($headertext) { 
            $url=$wgTitle->getPrefixedText();
            $dateasc  = "[[" . $url . "/order=year|&darr;]]";
            $datedesc = "[[" . $url . "/order=!year|&uarr;]]";
            $srcasc   = "[[" . $url . "/order=page|&darr;]]";
            $srcdesc  = "[[" . $url . "/order=!page|&uarr;]]";
            $descasc  = "[[" . $url . "/order=desc|&darr;]]";
            $descdesc = "[[" . $url . "/order=!desc|&uarr;]]";
            $header = "\n|- align=\"center\" \n! Date $dateasc $datedesc !! Source $srcasc $srcdesc !! align=\"left\" | Description $descasc $descdesc\n";
        } else {
            $header = null;
        }                        
        $outputshell = "\n{| $tabledefs $tabletitle\n$header%%CONTENT%%\n|}";
        $tablemode = true;
        if (!$disptext) // no display mode was picked for table mode, make our own, date only since it's in a table
            $disptext = "'''%Y%-%m%-%d%'''";
        if ($tablemode) { // since we're in table mode, the DISPLAY parameter applies to the date
            $disptext = "\n|-\n|| " . $disptext . "||%source%\n||%description%";
        }
    } else {
    # looks like we're doing a list.
        if (!$disptext) // no display mode was picked for list mode, so let's use a default
            $disptext = $wgLifeMarkDefaultListDisplay;
        if ($title) { $title = "$input<br />"; }
        if ($styletext) $styledefs ="style=\"$styletext\"";
        if ($classtext) $classdefs ="class=\"$classtext\"";
        $outputshell = "<div $styledefs $classdefs>$title" . "%%CONTENT%%</div>";
    }
 
 
    #execute the SQL
    $res = $dbr->select(
                $wgLifeMarkDBPrefix.'lifemarks',
                array('page_id','year','month','day','description','tags'),
                $where, 'Database::select',
                $options
            );
    if (!$res) { return(0); }
 
    #loop through the SQL and find events
    while ($lm = $dbr->fetchRow($res)) {
        $page_id = $lm['page_id'];
        $year = $lm['year'];
        $month = $lm['month'];
        $day = $lm['day'];
        $description = $lm['description'];
        $tags = $lm['tags'];
        $page_title = $page_titles[$page_id]; // this keeps a temp cache of page titles
        if (!$page_title) { 
            $page_titles[$page_id] = Title::nameOf($page_id);
            $page_title = $page_titles[$page_id];
        }
        if ($sourcetag=="title") { 
            $pagesource = "[[$page_title]]";  
        } elseif ($sourcetag) { //anything besides the word "name" becomes the linktext
            $pagesource = "([[:$page_title|$sourcetag]])"; 
        } else {
            $pagesource = "";
        }
 
        $output.=formatLifeMark(
                $disptext,
                $year,
                $month,
                $day,
                $description,
                $tags,
                $pagesource,
                false//true //DO NOT PERFORM WIKI MARKUP, WE'LL DO THAT OURSELVES SHORTLY.
            );
        $count++;
    }
 
    $dbr->freeResult( $res );
 
    if (!$count) {
        $output.="No lifemarks found!";
    }
 
 
    $complete_output  = str_replace("%%CONTENT%%", $output, $outputshell);
 
    # now process the $outputshell which will convert any wikimarkup
    $localParser = new Parser();
    $tempoutput = $localParser->parse($complete_output, $wgTitle, $wgOut->mParserOptions, false);
    $output = $tempoutput->getText();
 
 
    return($output);
}
 
 
 
 
function wfSpecialLifeMarks() {
        require_once('SpecialPage.php');
 
        # complete the messages that will be used :
        global $wgMessageCache ;
                $wgMessageCache->addMessages(array(
                'lifemarks' => 'LifeMarks' ,
        ));
 
        class SpecialPage_LifeMarks extends SpecialPage
        {
                # constructor
                function SpecialPage_LifeMarks($restriction = '') {
                        SpecialPage::SpecialPage('LifeMarks', $restriction ) ;
                }
 
                # override of the abstract execute() function, manages the output
                function execute($args_string = '') {
                        global $wgOut, $wgTitle, $wgParser;
                        $dbr =& wfGetDB( DB_MASTER );
 
                        # Parse arguments.
                        $args = array();
                        foreach (explode('/',$args_string) as $pair) {
                                $pair = explode('=',$pair);
                                $args[$pair[0]] = $pair[1];
                        }
 
                        $title = "LifeMarks";
                        $args['header'] = 1;  // Make sure that a header is displayed
                        $args['format'] = "table"; //The Special Page will always list in table format
                        $args['style'] = "border: 1px solid black;";
                        $args['sourcelinktext'] = "title";
 
                        # parse the parameters
                        if ($args['order'])    $args['orderby'] = $args['order'];
                        if ($args['year']) {
                                $title.= ' in year(s) ' . $args['year'];
                        }
                        if ($args['month']) {
                                $title.= ' in month(s) ' . $args['month'];
                        }
                        if ($args['day']) {
                                $title.= ' on day(s) ' . $args['day'];
                        }
                        if ($args['tags']) {
                                $title.= ' whose tags include "' . $args['tags'] .'"';
                        }
                        if ($args['page']) {
                                $page_title = Title::nameOf($args['page']);
                                $title.= ' found on page ' . $page_title;
                        }
 
 
                        $wgOut->setPageTitle($title);
                        $wgOut->addWikiText("This page will list all LifeMarks found in the Wiki.  You can arrange them by date, source page or description.  Technically, you can also list them by tags but I haven't coded that in yet.  I'd also like to allow you to limit the selection to just one namespace, but I'm beginning to think that my method of passing parameters to this page (in the form of url parameters like <code>/year=1999/order=!month</code>) is a bit too obtuse for that.  I'm looking for comments for improvement.");
                        $wgOut->addWikiText("Next on the list of Things To Do&trade; would be to put a form on this page allowing you to type in a month or year to filter the list.");
                        $output = renderLifeMarksList($title,$args);
                        $wgOut->addHTML($output);                
 
                        # http://meta.wikimedia.org/wiki/Talk:Permissions (Error message with MediaWiki v1.6.5)
                        # explains line below
                        $wgOut->setArticleFlag( false );
                }
        }
 
        SpecialPage::addPage ( new SpecialPage_LifeMarks() ) ;
}
Personal tools
Namespaces
Variants
Actions
Site
Support
Download
Development
Communication
Print/export
Toolbox