Extension:LifeMarks: Difference between revisions
LifeMarks Extension released |
m Added the category tag |
||
| Line 926: | Line 926: | ||
I tried to stay organized with this, but the bigger it became, the harder it was to keep the bloat and sprawl away. I've probably written a lot of spaghetti here, so I ask for comment from anyone brave enough to dive in. I'm fairly satisfied with my first attempt at an extension, and I hope that some of you find it useful. Feel free to use the Talk page for comments or requests.<br/> |
I tried to stay organized with this, but the bigger it became, the harder it was to keep the bloat and sprawl away. I've probably written a lot of spaghetti here, so I ask for comment from anyone brave enough to dive in. I'm fairly satisfied with my first attempt at an extension, and I hope that some of you find it useful. Feel free to use the Talk page for comments or requests.<br/> |
||
--[[User:Bakerq|Bakerq]] 19:57, 9 September 2006 (UTC) |
--[[User:Bakerq|Bakerq]] 19:57, 9 September 2006 (UTC) |
||
[[Category:Extensions|ExpandCss]] |
|||
Revision as of 19:57, 9 September 2006
Release status: unknown |
|
|---|---|
| Description | Mark notable dates and events for collection and display |
| Author(s) | User:Bakerq |
| Latest version | 0.1.0 (2006-09-9) |
| MediaWiki | developed on 1.6.8 |
| Licence | No licence specified |
| Download | Copy from this page |
LifeMarks is an extension for MediaWiki that will allows you to add simple tags to articles consisting of a date and a description, with the goal of marking a date with an event; these dates could be collected into a timeline of events. This is my first extension written for MediaWiki, developed for version 1.6.8. I created it because the Events Extension, while very close to my needs, lacked some of the capability I needed. Also, I became somewhat enamored with the idea of filling out a wiki and (once a goodly number of events are recorded) using the events list to fill out a timeline.
Introduction
This extension was jumpstarted by borrowing code from the Events Extension and Tasks Extension, notably the database interface. I corrected the bug that resulted from a double-call of the parse() function (this would clobber any other extensions on the page and render them into UNIQ tags).
This extension introduces two new tags for use in an article. The first, <lifemark> is used to set an event marker on a date. The second, <lifemarklist> will render a list of all lifemarkers across the wiki that matches given criteria.
In its most simple form:
<lifemark>1533-09-07: Queen Elizabeth I born</lifemark>
This would create an event marker on the date of September 7, 1533, described as "Queen Elizabeth I born".
LifeMarks can further be given category tags for easy lookup later, such as listing all categories tagged with the word "births":
<lifemark tags="births">1533-09-07: [[w:Elizabeth I of England|Queen Elizabeth I]] born</lifemark>
All lifemarks can be listed in either a table or straight list by calling the <lifemarklist> tag. Following the above example, to display all LifeMarks tagged with the word "births":
<lifemarklist tags="births">List of Births</lifemarklist>
As you can see, the text in between the <lifemarklist> tags is the title of the list returned. Also, all texts provided (desciptions and titles) can include wiki-markup.
Using <LifeMarks>
LifeMarks can be set anywhere in any article. By default, they produce no output, so they're safe to use in the middle of a paragraph or block of text where appropriate.
LifeMark Syntax
LifeMarks can be called simply in the form of (which by default produces no output):
<lifemark>yyyy-mm-dd: Description or Title</lifemark>
Or with optional display and organizational parameters:
<lifemark display="display_def" tags="tagging_text">yyyy-mm-dd: Description or Title</lifemark>
Finally, multiple lifemarks can be set within a single tag. In this form, all lifemarks will receive the same display styling and tagging text as defined in the <lifemark>:
<lifemark display="display_def" tags="tagging_text">
yyyy-mm-dd: Description
yyyy-mm-dd: Description
yyyy-mm-dd: Description
yyyy-mm-dd: Description
</lifemark>
Customizing LifeMarks Display
| What it looks like | What you type |
|---|---|
|
The default display keyword is "none". This produces no output as shown in a simple lifemark:
The following keywords are also available: |
The default display keyword is "none". This produces no output as shown in a simple lifemark: <lifemark>1999-9-9: Simple Lifemark</lifemark> The following keywords are also available: |
September 9th, 1990 |
; date : <lifemark display="date"> 1990-9-9: Lifemark with display keyword: "date" </lifemark> |
09/09/91 |
<nowiki>; slashdate : <lifemark display="slashdate"> 1991-9-9: Lifemark with "slashdatedate" display keyword: "slashdate" </lifemark> |
Sep 9, 1993 |
; meddate : <lifemark display="meddate"> 1993-9-9: Lifemark with "meddate" display keyword: "meddate" </lifemark> |
September 9th, 1992 |
; longdate : <lifemark display="longdate"> 1992-9-9: Lifemark with "longdate" display keyword: "longdate" </lifemark> |
|
Notice that the date-based keywords do not contain line-breaks. This allows them to be used inside a paragraph and contribute to its composition. In the following line of text, the date is generated by a lifemark tag with the display set to "longdate": The Y2K bug came and went on January 1st, 2000 with little tragedy. |
Notice that the date-based keywords do '''not''' contain line-breaks. This allows them to be used inside a paragraph and contribute to its composition. In the following line of text, the date is generated by a lifemark tag with the display set to "longdate": The Y2K bug came and went on <lifemark display="longdate">2000-01-01: Y2K non-event</lifemark> with little tragedy. |
|
Event-based dispay keywords contain the desciption or title text given with the tag:
09-09-1994: Lifemark with display keyword: "event" |
Event-based dispay keywords contain the desciption or title text given with the tag: ; event : <lifemark display="event"> 1994-9-9: Lifemark with display keyword: "event" </lifemark> |
September 9th, 1996: Lifemark with display keyword: "longevent" |
; longevent : <lifemark display="longevent"> 1996-9-9: Lifemark with display keyword: "longevent" </lifemark> |
Sep 9, 1998: Lifemark with display keyword: "medevent" |
; medevent : <lifemark display="medevent"> 1998-9-9: Lifemark with display keyword: "medevent" </lifemark> |
09/09/00: Lifemark with display keyword: "slashevent" |
; slashevent : <lifemark display="slashevent"> 2000-9-9: Lifemark with display keyword: "slashevent" </lifemark> |
|
For convenience, each of the event-type display keywords also contain a plural form: events, longevents, medevents, and slashevents. Each of these display keywords end with a line-break, allowing lists to be formatted easily for multiple lifemarks.
January 20th, 1989: George H. W. Bush inaugurated |
For convenience, each of the event-type display keywords also contain a plural form: '''events''', '''longevents''', '''medevents''', and '''slashevents'''. Each of these display keywords end with a line-break, allowing lists to be formatted easily for multiple lifemarks. ; events : <lifemark display="longevents"> 1989-1-20: George H. W. Bush inaugurated 1993-1-20: Bill Clinton inaugurated 2001-1-20: George W. Bush inaugurated </lifemark> |
|
Finally, if none of these keywords fit, you can define your own. You can construct a display tag with the variables %year%, %month%, %day% and %description%. New Years Day (01-01-2006) |
Finally, if none of these keywords fit, you can define your own. You can construct a display tag with the variables '''%year%''', '''%month%''', '''%day%''' and '''%description%'''. <lifemark display="%description% (%month%-%day%-%year%)"> 2006-01-01: New Years Day </lifemark> |
|
If you're familiar with the PHP function
1990-05-05 |
If you're familiar with the PHP function <code>date()</code> then you may recognize a few of these display variables, wrapped with '''%''' marks. *'''%year%''' is the same as '''%Y%''', a 4-digit year. *'''%month%''' is the same as '''%m%''', a 2-digit month. *'''%day%''' is the same as '''%d%''', a 2-digit day. <lifemark display="%Y%-%m%-%d%">1990-05-05: Cinco de Mayo!</lifemark> |
|
Other
7/4/76 Declaration of Independence Lastly there are the names of the month in both long and short form, and a suffix for the day.
Valentines Day fell on Feb 14th of 2004 |
Other <code>date()</code> variables that can be used are: *'''%y%''' is a 2-digit year. *'''%j%''' is the day with no leading zeros. *'''%n%''' is the month with no leading zeros. <lifemark display="%n%/%j%/%y% %description%"> 1776-07-04: Declaration of Independence </lifemark> Lastly there are the names of the month in both long and short form, and a suffix for the day. *'''%F%''' is the full month name, like "January". *'''%M%''' is the abbreviated month name, "Jan" *'''%S%''' is the "st" in "1st", the "nd" in "2nd" *:the "rd" in "3rd" and the "th" in every other day. <lifemark display="%description% fell on %M% %j%%S% of %Y%"> 2004-02-14: Valentines Day </lifemark> |
Using <LifeMarkList>
In the course of demonstrating the above, we've created a goodly number of lifemarks. Setting dates and events would be useless if there was no way to collect them and display them, which is where the <lifemarklist> comes in. LifeMarkLists, by default, are not returned in tables. They come out as straight text with a title, a hard line break, and then a list of lifemarkers that each use the events display keyword. (For tables, see below) The text in between the <lifemarklist> tags will become the title of the list. Just as with the <lifemark> tag, there are a number of display parameters and filtering parameters you can pass.
LifeMarkList Syntax
Generating a LifeMarkList of all LifeMarkers in the wiki is possible simply by using:
<nowiki><lifemarklist>List of LifeMarks</lifemarklist>
You can even remove the title by simply calling: <lifemarklist/> for a streamlined, no-options-at-all list of LifeMarks. There are, however, a great number of parameters that can be passed to the list to control its display and behavior.
<lifemaklist year="year_filter" month="month_filter" day="day_filter" page="source_page_filter" limit="number_of_markers" offset="skipped_markers" display="display_template" format="list|table" orderby="sort_order" sourcelinktext="link_word" border="table_border_size" cellpadding="padding_size" cellspacing="spacing_size" style="css_style" class="css_class">Title Goes here</lifemarklist>
Customizing LifeMarkList Display
To limit the number returned, simply specify the criteria in the tag. For example:
<lifemarklist year="1993">Events in 1993</lifemarklist>
would list all lifemarkers in 1993. You can limit by year, month, day, source page_id, or by tags. For the first three, you can even specify a range, such as 1990-1992. Thus, the following:
<lifemarklist year="1992-2006" month="12" day="25" tags="happy">Happy Christmas dates in Vermont</lifemarklist>
would show all events that occured on December 25, during the years 1992 to 2006 and tagged with the word "happy". Listing all lifemarks from one page in the Wiki requires knowledge of that article's page_id. Users will rarely know or care about an article's page ID, however, by using the word "current", you can list all LifeMarkers defined on the current page.
<lifemarklist page="current">All events found on this page</lifemarklist>
Further ways to limit the display would be to set a limit on the number of events returned (limit="5"), or specifying the offset (offset=12).
You can change the order of events displayed as well. By default, the events are ordered chronologically starting with the earliest date. To list the events by month, you can use orderby="month", or by years in reverse order, "orderby=!year". The available sort methods are year, month, day, desccription, tags, page_id. Each method can be reversed by placing a ! in front, so !desc would list LifeMarkers by description in reverse alphabetical order.
Finally, you can set a display which is nearly identical to the display parameter on the <lifemarklist> tag, with a few notable exceptions. Firstly, it supports a display variable %source% which is replaced with a link to the page that has the LifeMarker in question. To extend this even further, you can pass another parameter, sourcelinktext which will become the link text. By default, this is "(src)". If you want the link to be the title of the origin page, use sourcelinktext="title".
The list can easily be returned in the form of a table as well. If you specify a border, cellpadding, cellspacing, style or class, or if you specify format="table", a table will be returned. (To apply a CSS class or style to a list, use format="list" to force a list-based output, but it's not guaranteed that the style will be applied properly throughout.) The table returned will place the table in the top row (colspan=3) and have columns for the date, source link, and description. When table output is used, the display parameter applies only to the date field. Placing the variable %description% in the display paramter for a table output would display the description twice: once in the description column and once crammed into the date column.
Special Page
A SpecialPage called LifeMarks will allow for collecting all LifeMarks and displaying them in order. They can also be filtered by year, month, day, source pages, description or (most likely) tag texts. (Although not through a web interface. That's a feature for the next version or an intrepid hacker.)
The SpecialPage differs from the usage of a <lifemarklist> tag in that it has links at the top of the table which can change the sort order immediately via up and down arrows next to the date, source, and description headers.
The source page definitions are included in the LifeMarks.php file, so no extra files are needed to be installed in other directories.
Future plans (beyond the simple filtering form fields) include a rudementary duplicate search.
Global Settings
The following Global Settings can be set in your LocalSettings.php file to alter the basic options of the LifeMarkers Extension.
- $wgLifeMarkDefaultDisplay
- If you require a prefix before your MySQL table names, include it with this setting. This string will be prefixed before all SQL calls.
- $wgLifeMarkDefaultDisplay
- Defaults to "none". By default, the <lifemark> tag produces no output. If you would like to define a default display, place it here.
- $wgLifeMarkDefaultListDisplay
- Defaults to "events". Similarly, the <lifemarklist> tag, when in list mode, display by default according to the events keyword. Change its default here.
- $wgLifeMarkDefaultOrderBy =
- Defaults to: 'year ASC, month ASC, day ASC, description ASC'. If you would like to change the default order that LifeMarkLists are displayed in, place it here. Please note that this is the SQL order which is appended directly to the end of the MySQL SELECT statement. This does not support the OrderBy keywords above.
Ideas
One possible further parament to the <lifemark> tag, fuzziness, would be a number of days (or more likely weeks) with which the date is fuzzy. Namily, if you have an event that took place in the Summer of 1985, you could set the date as July-1-1975 with a fuzziness of 8 weeks.
Installation
This extension saves all of its information in a MySQL table, which means you must run the following SQL command to create the space for its data. Read the note below if you use table 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 );
Place the source code below into a file called LifeMarks.php in your extensions directory. Then add the following line to your LocalSettings.php file:
require_once("extensions/LifeMarks.php");
If you require a SQL table prefix, alter the SQL code above to include it in the CREATE line. You must also set up the global setting $wgLifeMarkDBPrefix in your LocalSettings.php.
Source:
<?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!
*/
$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
# NOW FOR ENGLISH MONTH NAMES. TODO, LET'S INTERNATIONALIZE THIS, EH?
$monthname[1] = array( 's'=>'Jan', 'l' => 'January' );
$monthname[2] = array( 's'=>'Feb', 'l' => 'February' );
$monthname[3] = array( 's'=>'Mar', 'l' => 'March' );
$monthname[4] = array( 's'=>'Apr', 'l' => 'April' );
$monthname[5] = array( 's'=>'May', 'l' => 'May' );
$monthname[6] = array( 's'=>'Jun', 'l' => 'June' );
$monthname[7] = array( 's'=>'Jul', 'l' => 'July' );
$monthname[8] = array( 's'=>'Aug', 'l' => 'August' );
$monthname[9] = array( 's'=>'Sep', 'l' => 'September' );
$monthname[10] = array( 's'=>'Oct', 'l' => 'October' );
$monthname[11] = array( 's'=>'Nov', 'l' => 'November' );
$monthname[12] = array( 's'=>'Dec', 'l' => '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|↓]]";
$datedesc = "[[" . $url . "/order=!year|↑]]";
$srcasc = "[[" . $url . "/order=page|↓]]";
$srcdesc = "[[" . $url . "/order=!page|↑]]";
$descasc = "[[" . $url . "/order=desc|↓]]";
$descdesc = "[[" . $url . "/order=!desc|↑]]";
$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™ 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 Thoughts
I tried to stay organized with this, but the bigger it became, the harder it was to keep the bloat and sprawl away. I've probably written a lot of spaghetti here, so I ask for comment from anyone brave enough to dive in. I'm fairly satisfied with my first attempt at an extension, and I hope that some of you find it useful. Feel free to use the Talk page for comments or requests.
--Bakerq 19:57, 9 September 2006 (UTC)
