I've made some changes to Parser.php on my local install to make
category pages a little neater. You can take a look at
http://meta.wikipedia.org/wiki/Image:Category_sort_example.png for a
fairly recent screenshot.
Things changed are
* Three column view of sub categories and articles
* List view of subcategories and articles (if there are only a few)
* headings for the first letter of sort keys in article and subcategory
lists
* "Category" doesn't appear before subcategories and
* Display of the number of articles and subcategories.
I have no idea if this code is safe/well thought out/whatever but it
works fine on my local mediawiki installation.
And no picking on my php skills ;-)
Tobin.
My version of the categoryMagic function follows. Just about everything
after "# For all pages that link to this category" is changed.
----
# This method generates the list of subcategories and pages for a
category
function categoryMagic ()
{
global $wgLang , $wgUser ;
if ( !$this->mOptions->getUseCategoryMagic() ) return ; # Doesn't use
categories at all
$cns = Namespace::getCategory() ;
if ( $this->mTitle->getNamespace() != $cns ) return "" ; # This
ain't
a category page
$r = "<br style=\"clear:both;\"/>\n";
$sk =& $wgUser->getSkin() ;
$articles = array() ;
$articles_start_char = array();
$children = array() ;
$children_start_char = array();
$data = array () ;
$id = $this->mTitle->getArticleID() ;
# FIXME: add limits
$t = wfStrencode( $this->mTitle->getDBKey() );
$sql = "SELECT DISTINCT cur_title,cur_namespace,cl_sortkey FROM
cur,categorylinks WHERE cl_to='$t' AND cl_from=cur_id ORDER BY
cl_sortkey" ;
$res = wfQuery ( $sql, DB_READ ) ;
while ( $x = wfFetchObject ( $res ) ) $data[] = $x ;
# For all pages that link to this category
foreach ( $data AS $x )
{
$t = $wgLang->getNsText ( $x->cur_namespace ) ;
if ( $t != "" ) $t .= ":" ;
$t .= $x->cur_title ;
if ( $x->cur_namespace == $cns ) {
array_push ( $children, $sk->makeKnownLink ( $t, $x->cur_title) ) ;
# Subcategory
array_push ( $children_start_char, $x->cl_sortkey[0]) ;
} else {
array_push ( $articles , $sk->makeLink ( $t ) ) ; # Page in this
category
array_push ( $articles_start_char, $x->cl_sortkey[0]) ;
}
}
wfFreeResult ( $res ) ;
# Showing subcategories
if ( count ( $children ) > 20) {
$ti = $this->mTitle->getText() ;
// divide list into three equal chunks
$chunk = (int) (count ( $children ) / 3);
// get and display header
$h = wfMsg( "subcategories" );
$r .= "<h2>{$h}</h2>\n" ;
$r .= "There are ".count( $children )." subcategories to this
category<br>" ;
$r .= "<table width=\"100%\"><tr
valign=\"top\">";
$startChunk = 0;
$endChunk = $chunk;
// loop through the chunks
for($startChunk = 0, $endChunk = $chunk, $chunkIndex = 0;
$chunkIndex < 3; $chunkIndex++, $startChunk = $endChunk, $endChunk +=
$chunk + 1)
{
$r .= "<td>";
$r .= "<ul>";
// output all subcategories to category
for ($index = $startChunk ; $index < $endChunk && $index <
count($children); $index++ )
{
// check for change of starting letter or begging of chunk
if ($children_start_char[$index] != $children_start_char[$index -
1] || $index == $startChunk )
{
$r .= "</ul>";
$r .=
"<h3>".$children_start_char[$index]."</h3>\n";
$r .= "<ul>";
}
$r .= "<li>".$children[$index]."</li>";
}
$r .= "</ul>";
$r .= "</td>";
}
$r .= "</tr></table>";
} else {
// for short lists of subcategories to category.
$ti = $this->mTitle->getText() ;
$h = wfMsg( "subcategories" );
$r .= "<h2>{$h}</h2>\n" ;
$r .= "There are ".count( $children )." subcategories to this
category<br>" ;
$r .= "<h3>".$children_start_char[0]."</h3>\n";
$r .= "<ul><li>".$children[0]."</li>";
for ($index = 1; $index < count($children); $index++ )
{
if ($children_start_char[$index] != $children_start_char[$index -
1])
{
$r .= "</ul>";
$r .= "<h3>".$children_start_char[$index]."</h3>\n";
$r .= "<ul>";
}
$r .= "<li>".$children[$index]."</li>";
}
$r .= "</ul>";
}
# Showing articles in this category
if ( count ( $articles ) > 20) {
$ti = $this->mTitle->getText() ;
// divide list into three equal chunks
$chunk = (int) (count ( $articles ) / 3);
// get and display header
$h = wfMsg( "category_header", $ti );
$r .= "<h2>{$h}</h2>\n" ;
$r .= "There are ".count( $articles )." articles in this
category<br>";
$r .= "<table width=\"100%\"><tr
valign=\"top\">";
// loop through the chunks
for($startChunk = 0, $endChunk = $chunk, $chunkIndex = 0;
$chunkIndex < 3; $chunkIndex++, $startChunk = $endChunk, $endChunk +=
$chunk + 1)
{
$r .= "<td>";
$r .= "<ul>";
// output all articles in category
for ($index = $startChunk ; $index < $endChunk && $index <
count($articles); $index++ )
{
// check for change of starting letter or begging of chunk
if ($articles_start_char[$index] != $articles_start_char[$index -
1] || $index == $startChunk )
{
$r .= "</ul>";
$r .=
"<h3>".$articles_start_char[$index]."</h3>\n";
$r .= "<ul>";
}
$r .= "<li>".$articles[$index]."</li>";
}
$r .= "</ul>";
$r .= "</td>";
}
$r .= "</tr></table>";
} else {
// for short lists of articles in categories.
$ti = $this->mTitle->getText() ;
$h = wfMsg( "category_header", $ti );
$r .= "<h2>{$h}</h2>\n" ;
$r .= "There are ".count( $articles )." articles in this
category<br>" ;
$r .= "<h3>".$articles_start_char[0]."</h3>\n";
$r .= "<ul><li>".$articles[0]."</li>";
for ($index = 1; $index < count($articles); $index++ )
{
if ($articles_start_char[$index] != $articles_start_char[$index -
1])
{
$r .= "</ul>";
$r .= "<h3>".$articles_start_char[$index]."</h3>\n";
$r .= "<ul>";
}
$r .= "<li>".$articles[$index]."</li>";
}
$r .= "</ul>";
}
return $r ;
}