User:Socoljam/DynamicArticleList (enhanced)
Dynamic Article List is a great extension, but it had two little problems for me:
- You could not parse Wikitext in the title field (for example, to add a link)
- All the information was too wide or caused weird linebreaks
So I updated it a little. Now the opening tag accepts three optional parameters, showtimestamp, showeditor, and showviews
. These all default to 1, but if set to 0, will hide the timestamp, the editor, or the view count, respectively, if they were generated by whatever type of list you have. I also let the $parser object take a crack at the title, and now you can add wikimarkup to that field.
Installation
[edit]This installs exactly like Dynamic Article List, except replace DynamicArticleList.php with the code below. You still need the other files listed on the main site:
- Download these files and copy the content to appropriately named PHP files:
- Save the three PHP files into your includes directory.
- Copy and paste the code (below) into your favorite editor and save it as DynamicArticleList.php in your extensions directory.
- Add the following line to your LocalSettings.php file, after
require_once( "DefaultSettings.php" );
:require_once( "extensions/DynamicArticleList.php" );
Usage
[edit]Tag and its Attributes and Parameters
[edit]Tag Name | DynamicArticleList | ||
Attributes | Attribute | Description | Default |
showeditor (optional) | If set to 0, hides the last editor in new/update/discussion lists | 1 | |
showtimestamp (optional) | If set to 0, hides the timestamp in new/update/discussion lists | 1 | |
showviews (optional) | If set to 0, hides the number of views in a hot list | 1 | |
Parameters | Parameter | Description | Default |
title (optional) | Title of the output article list | blank | |
type (optional) | Type of dynamic article list (new/update/discussion/hot) | new | |
count (optional) | Output count of articles | 5 | |
categoryRoot (optional) | Name of category where (including its children) all articles reside | blank |
Note:
- If "categoryRoot" is set, Dynamic Article List will only retrieve articles in this category and its children. If not, all articles will be candidates.
- The value of parameter "type" could be one of the following (default is new ):
- new => Newly Posted Articles
- update => Recently Updated Articles
- discussion => Recent Discussions
- hot => Most Popular Articles
Examples
[edit]So, for example, the following code would create a "new article" style list, with a link in the title to an article, and would show the timestamp but not the last editor:
<DynamicArticleList showeditor=0> title=New Articles in [[History]] type=new categoryRoot=History </DynamicArticleList>
This example would create a discussion list, but would hide the timestamp:
<DynamicArticleList showtimestamp=0> title=Recent [[Project:Talk pages|Discussion]] type=discussion count=10 </DynamicArticleList>
This would create a "hot" list, but hide the view counts:
<DynamicArticleList showviews=0> type=hot </DynamicArticleList>
Compatibility
[edit]This version is not compatible with MediaWiki pre-1.5, since it assumes the tag attributes are passed as an array. (It would be very easy to add backwards compatibility.) And since DynamicArticleList requires PHP5 anyway, that should not pose much of a problem. (Just upgrade to 1.7.1.)
Code
[edit]So here's the code. Save the following as DynamicArticleList.php and put it in your extensions directory. (See #Installation)
<?php /* * Purpose: Dynamic Output of Article List (Main Page always not in list) * Note: Currently support four types (new, hot, update, discussion). * new => Newly Posted Articles * update => Recently Updated Articles * hot => Most Popular Articles * discussion => Recently Updated Discussion * @author: Zeng Ji (zengji@gmail.com) * * To install, add following to LocalSettings.php * require_once ("extensions/DynamicArticleList.php"); */ $wgExtensionFunctions[] = "wfDynamicArticleList"; function wfDynamicArticleList() { global $wgParser; $wgParser->setHook( "DynamicArticleList", "DynamicArticleList" ); } // The callback function for converting the input text to HTML output function DynamicArticleList( $input, $getOpts, &$parser ) { require_once ('CategoryUtil.php'); $dbr =& wfGetDB( DB_SLAVE ); // INVALIDATE CACHE global $wgTitle; $wgTitle->invalidateCache(); // Default Values $listTitle = false; $listType = 'new'; $listCount = 5; $categoryRoot = false; $options = array('showeditor' => 1, 'showtimestamp' => 1, 'showviews' => 1 ); foreach ( $getOpts as $k => $v ) { $options[$k] = $v; } // ###### PARSE PARAMETERS ###### $aParams = explode("\n", $input); foreach($aParams as $sParam) { $aParam = explode("=", $sParam); if( count( $aParam ) < 2 ) continue; $sType = trim($aParam[0]); $sArg = trim($aParam[1]); switch ($sType) { case 'title': $listTitle = $sArg; break; case 'type': if ( in_array($sArg, array('new','hot','update', 'discussion')) ) $listType = $sArg; break; case 'count': $listCount = IntVal( $sArg ); break; case 'categoryRoot': $categoryRoot = $sArg; break; } } // ###### CHECKS ON PARAMETERS ###### if ($listTitle!=false && strlen($listTitle)==0) { $listTitle=false; } else { $parseTitle = $parser->parse($listTitle, $parser->mTitle, $parser->mOptions, false, false); $listTitle = $parseTitle->getText(); } // ###### BUILD SQL QUERY ###### $sql = genSQL($listType, $listCount, $categoryRoot); // ###### PROCESS SQL QUERY ###### global $wgUser; global $wgLang; global $wgContLang; $res = $dbr->query($sql); $sk =& $wgUser->getSkin(); if ($dbr->numRows( $res ) != 0) { while( $row = $dbr->fetchObject ( $res ) ) { $title = Title::makeTitle( $row->namespace, $row->title); if ($listType == 'discussion') $sLink = $sk->makeKnownLinkObj($title, $wgContLang->convertHtml($title->getText()), '', '', 'Discussion: '); else $sLink = $sk->makeKnownLinkObj($title, $wgContLang->convertHtml($title->getText())); // Generate 'View Count' String (for 'hot') if ($listType == 'hot') $aViews[] = ' - ( ' . $row->count . ' views ) '; else $aViews = false; // Generate 'Time' String (for 'new', 'update', 'discussion') if ($listType != 'hot') { $aDates[] = ' - [ ' . $wgLang->timeanddate($row->timestamp, true) . ' ] '; $editorID = $row->user; if ($editorID == 0) { $editor = wfMsg('anonymous'); $aEditors[] = ' (' . $editor . ')'; } else { $editor = User::whoIs($editorID); $aEditors[] = ' ( ' . $sk->makeLink($wgContLang->getNsText(NS_USER) . ':' . $editor, htmlspecialchars($editor)) . ' )'; } } else { $aDates = false; $aEditors = false; } $aArticles[] = $sLink; } } $dbr->freeResult( $res ); // ###### GENERATE OUTPUT ###### return OutputList($aArticles, $aEditors, $aDates, $aViews, $listTitle, $options); } function genSQL( $type, $count, $categoryRoot=false ) { $dbr =& wfGetDB( DB_SLAVE ); $sPageTable = $dbr->tableName( 'page' ); $sRevisionTable = $dbr->tableName( 'revision' ); $sRecentChangesTable = $dbr->tableName( 'recentchanges' ); $sCategoryLinksTable = $dbr->tableName( 'categorylinks' ); $categoryUtil = new CategoryUtil(); $sql = ''; if ($type == 'hot') { if ($categoryRoot != false) { $cNameList = $categoryUtil->getCNameList($categoryRoot); $sql = " SELECT DISTINCT page_title as title, page_namespace AS namespace, page_counter as count FROM $sPageTable INNER JOIN $sCategoryLinksTable ON page_id=cl_from WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0 AND page_id!=1 AND cl_to IN ".$cNameList." ORDER by count DESC LIMIT $count "; } else { $sql = " SELECT DISTINCT page_title as title, page_namespace AS namespace, page_counter as count FROM $sPageTable WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0 AND page_id!=1 ORDER by count DESC LIMIT $count "; } } elseif ($type == 'update') { // Step 1: Get revision list order by rev_id if ($categoryRoot != false) { $cNameList = $categoryUtil->getCNameList($categoryRoot); $sql = " SELECT page_id, MAX(rev_id) AS max_rev_id FROM $sPageTable INNER JOIN $sRevisionTable ON page_id=rev_page INNER JOIN $sCategoryLinksTable ON page_id=cl_from WHERE page_is_new!=1 AND page_namespace=0 AND page_is_redirect=0 AND page_id!=1 AND cl_to IN ".$cNameList." GROUP BY page_id ORDER by max_rev_id DESC LIMIT $count "; } else { $sql = " SELECT page_id, MAX(rev_id) AS max_rev_id FROM $sPageTable INNER JOIN $sRevisionTable ON page_id=rev_page WHERE page_is_new!=1 AND page_namespace=0 AND page_is_redirect=0 AND page_id!=1 GROUP BY page_id ORDER by max_rev_id DESC LIMIT $count "; } // Step 2: According to revision list, generate SQL to retrieve article page information. $res = $dbr->query($sql); $inClause = ''; if ($dbr->numRows( $res ) == 0) { $inClause = "-1"; } else { while( $obj = $dbr->fetchObject( $res ) ) { if( isset( $obj->max_rev_id ) ) { $inClause .= $obj->max_rev_id . ','; } } $inClause = substr($inClause, 0, -1); //delete tailing ',' } $dbr->freeResult( $res ); $sql = " SELECT page_title AS title, page_namespace AS namespace, rev_user AS user, rev_timestamp AS timestamp FROM $sRevisionTable, $sPageTable WHERE rev_page=page_id AND rev_id IN (". $inClause . ") ORDER BY rev_id DESC"; } elseif ($type == 'discussion') { // Step 1: Get revision list order by rev_id. if ($categoryRoot != false) { $cNameList = $categoryUtil->getCNameList($categoryRoot); $sql = " SELECT p1.page_id, MAX(rev_id) AS max_rev_id FROM $sPageTable AS p1 INNER JOIN $sPageTable AS p2 ON p1.page_title=p2.page_title INNER JOIN $sRevisionTable ON p1.page_id=rev_page INNER JOIN $sCategoryLinksTable ON p2.page_id=cl_from WHERE p1.page_is_redirect=0 AND p1.page_namespace=1 AND p2.page_namespace=0 AND cl_to IN ".$cNameList." GROUP BY rev_page ORDER by max_rev_id DESC LIMIT $count "; } else { $sql = " SELECT p1.page_id, MAX(rev_id) AS max_rev_id FROM $sPageTable AS p1 INNER JOIN $sRevisionTable ON p1.page_id=rev_page WHERE p1.page_is_redirect=0 AND p1.page_namespace=1 GROUP BY rev_page ORDER by max_rev_id DESC LIMIT $count "; } // Step 2: According to revision list, generate SQL to retrieve discussion page information. $res = $dbr->query($sql); $inClause = ''; if ($dbr->numRows( $res ) == 0) { $inClause = "-1"; } else { while( $obj = $dbr->fetchObject( $res ) ) { if( isset( $obj->max_rev_id ) ) { $inClause .= $obj->max_rev_id . ','; } } $inClause = substr($inClause, 0, -1); //delete tailing ',' } $dbr->freeResult( $res ); $sql = " SELECT page_title AS title, page_namespace AS namespace, rev_user AS user, rev_timestamp AS timestamp FROM $sRevisionTable, $sPageTable WHERE rev_page=page_id AND rev_id IN (". $inClause . ") ORDER BY rev_id DESC"; } else { // default type is 'new' if ($categoryRoot != false) { $cNameList = $categoryUtil->getCNameList($categoryRoot); $sql = " SELECT DISTINCT page_title AS title, page_namespace AS namespace, rc_user AS user, rc_timestamp AS timestamp FROM $sPageTable INNER JOIN $sRecentChangesTable ON page_id=rc_cur_id INNER JOIN $sCategoryLinksTable ON page_id=cl_from WHERE rc_new=1 AND rc_namespace=0 AND page_is_redirect=0 AND page_id!=1 AND cl_to IN ".$cNameList." ORDER by rc_id DESC LIMIT $count "; } else { $sql = " SELECT DISTINCT page_title AS title, page_namespace AS namespace, rc_user AS user, rc_timestamp AS timestamp FROM $sPageTable INNER JOIN $sRecentChangesTable ON page_id=rc_cur_id WHERE rc_new=1 AND rc_namespace=0 AND page_is_redirect=0 AND page_id!=1 ORDER by rc_id DESC LIMIT $count "; } } return $sql; } function OutputList ( $aArticles, $aEditors, $aDates, $aViews, $listTitle, $options ) { if ($listTitle != false) { $r .= " <h3>" . $listTitle . "</h3>\n"; $r .= " <hr/>\n"; } $sStartList = '<ul>'; $sEndList = '</ul>'; $sStartItem = '<li>'; $sEndItem = '</li>'; $r .= $sStartList . "\n"; for ($i=0; $i<count($aArticles); $i++) { $editorString = ""; $dateString = ""; $viewString = ""; if (($options['showeditor'] != 0)&&($aEditors != false)) $editorString = "<font size=-2>" . $aEditors[$i] . "</font>"; if (($options['showtimestamp'] != 0)&&($aDates != false)) $dateString = "<font size=-2>" . $aDates[$i] . "</font>"; if (($options['showviews'] !=0)&&($aViews != false)) $viewString = "<font size=-2>" . $aViews[$i] . "</font>"; $r .= $sStartItem . $aArticles[$i] . $editorString . $dateString . $viewString . $sEndItem . "\n"; } $r .= $sEndList . "\n"; return $r; } ?>