Page MenuHomePhabricator

DynamicPageList.php

Authored By
bzimport
Nov 21 2014, 8:10 PM
Size
16 KB
Referenced Files
None
Subscribers
None

DynamicPageList.php

<?php
/*
Purpose: outputs a bulleted list of most recent
items residing in a category, or a union
of several categories.
Contributors:
n:en:User:IlyaHaykinson n:en:User:Amgine w:de:Benutzer:Unendlich
http://en.wikinews.org/wiki/User:Amgine
http://en.wikinews.org/wiki/User:IlyaHaykinson
http://de.wikipedia.org/wiki/Benutzer:Unendlich
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.
http://www.gnu.org/copyleft/gpl.html
Current feature request list
1. RSS feed output?
To install, add following to LocalSettings.php
include("extensions/intersection/DynamicPageList.php");
*
@module DynamicPageList
@version $ID 2.0$
*/
$wgDLPminCategories = 1; // Minimum number of categories to look for
$wgDLPmaxCategories = 5; // Maximum number of categories to look for
$wgDLPMinResultCount = 1; // Minimum number of results to allow
$wgDLPMaxResultCount = 50; // Maximum number of results to allow
$wgDLPAllowUnlimitedResults = true; // Allow unlimited results
$wgDLPAllowUnlimitedCategories = false; // Allow unlimited categories
$wgExtensionFunctions[] = "wfDynamicPageList";
$wgExtensionCredits['parserhook'][] = array(
'name' => 'DynamicPageList',
'description' => 'outputs a bulleted list of the most recent items residing in a category, or a union of several categories',
'url' => 'http://meta.wikimedia.org/wiki/DynamicPageList'
);
function wfDynamicPageList() {
global $wgParser, $wgMessageCache;
$wgMessageCache->addMessages( array(
'dynamicpagelist_toomanycats' => 'DynamicPageList: Too many categories!',
'dynamicpagelist_toofewcats' => 'DynamicPageList: Too few categories!',
'dynamicpagelist_noresults' => 'DynamicPageList: No results!',
'dynamicpagelist_noincludecats' => 'DynamicPageList: You need to include at least one category, or specify a namespace!',
'dynamicpagelist_noincludedcatsbutcatdate' => 'DynamicPageList: You need to include at least one category to use \'addfirstcategorydate=true\' or \'ordermethod=categoryadd\'!',
'dynamicpagelist_morethanonecatbutcatdate' => 'DynamicPageList: If you include more than one category you cannot use \'addfirstcategorydate=true\' or \'ordermethod=categoryadd\'!',
'dynamicpagelist_catoutputwithwrongordermethod' => 'DynamicPageList: You need to use \'ordermethod=title\' when using category-style output!',
)
);
$wgParser->setHook( "DynamicPageList", "DynamicPageList" );
}
/* **
* function: setParams
* **
* Purpose: constructor, parse parameters
* parameters
* aCategories ARRAY category names
* aExcludeCategories ARRAY notcategory names
* bShowNamespace BOOL true = show namespace in link
* bNamespace BOOL true = only from namespace
* iNamspace INTEGER namespace id
* sOrder STRING sorting direction
* sOrderMethod STRING method of sorting to use
* bSuppressErrors BOOL true = do not return errors
* sRedirects STRING show, show only, or exclude redirects
* bAddFirstCategoryDate BOOL display date added to 1st category
* sStartList STRING HTML list type opening tag
* sEndList STRING HTML list type closing tag
* sStartItem STRING HTML list item opening tag
* sEndItem STRING HTML list item closing tag
* iCatCount INTEGER count of include categories
* iExcludeCatCount INTEGER count of exclued categories
* iTotalCatCount INTEGER count of both included and excluded
* bCountSet BOOL true = final category count determined
* iCount INTEGER total categories
* **
* @param STRING $input
* @return ARRAY $aParameters
* ** */
function setParams ( $input ) {
// Globals
global $wgContLang, $wgDLPminCategories;
global $wgDLPmaxCategories, $wgDLPMinResultCount, $wgDLPMaxResultCount;
global $wgDLPAllowUnlimitedResults, $wgDLPAllowUnlimitedCategories;
$aParameters = array(
'aCategories' => array(),
'aExcludeCategories' => array(),
'bShowNamespace' => true,
'aNamespace' => array(),
'abNamespace' => array(),
'sOrder' => 'descending',
'sOrderMethod' => 'lastedit',
'bSuppressErrors' => false,
'sRedirects' => 'exclude',
'bAddFirstCategoryDate' => false,
'sStartList' => '<ul>',
'sEndList' => '</ul>',
'sStartItem' => '<li>',
'sEndItem' => '</li>'
);
$aParams = explode("\n", $input);
// Loop through passed parameters
foreach ($aParams as $sParam) {
$aParam = explode('=', $sParam);
// if improper, skip
if ( count( $aParam ) < 2 ) continue;
$sType = trim($aParam[0]);
$sArg = trim($aParam[1]);
switch ( $sType ) {
case 'category':
$aCats = explode(',', $sArg);
$aaCats = array();
foreach($aCats as $sParam) {
$sParam=trim($sParam);
$title = Title::newFromText( $sParam );
if( $title != NULL ) $aaCats[] = $title;
}
if (!empty($aaCats)) $aParameters['aCategories'][] = $aaCats;
break;
case 'notcategory':
$title = Title::newFromText( $sArg );
// if not a real category, skip
if( is_null( $title ) ) continue;
$aParameters['aExcludeCategories'][] = $title;
break;
case 'namespace':
$aNS = explode(',', $sArg);
if (count($aNS)) {
// If second namespace assignment, reset the array
$aParameters['aNamespace'] = array();
$aParameters['abNamespace'] = array();
foreach ($aNS as $key => $sNS) {
$sNS = trim($sNS);
// check valid namespace value
$ns = $wgContLang->getNsIndex($sNS);
if (NULL != $ns) {
$aParameters['aNamespace'][$key] = $ns;
$aParameters['abNamespace'][$key] = true;
} else {
$aParameters['aNamespace'][$key] = intval($sNS);
if ($aParameters['aNamespace'][$key] >= 0) {
$aParameters['abNamespace'][$key] = true;
} else {
$aParameters['abNamespace'][$key] = false;
}
}
}
}
break;
case 'shownamespace':
if ('false' == $sArg) $aParameters['bShowNamespace'] = false;
else $aParameters['bShowNamespace'] = true;
break;
case 'mode':
switch ($sArg) {
case 'none':
$aParameters['sStartList'] = '';
$aParameters['sEndList'] = '';
$aParameters['sStartItem'] = '';
$aParameters['sEndItem'] = '<br/>';
$aParameters['bLastEndItem'] = false;
break;
case 'inline':
$aParameters['sStartList'] = '';
$aParameters['sEndList'] = '';
$aParameters['sStartItem'] = '';
$aParameters['sEndItem'] = ' - ';
$aParameters['bLastEndItem'] = false;
break;
case 'ordered':
$aParameters['sStartList'] = '<ol>';
$aParameters['sEndList'] = '</ol>';
$aParameters['sStartItem'] = '<li>';
$aParameters['sEndItem'] = '</li>';
$aParameters['bLastEndItem'] = true;
break;
case 'unordered':
default:
$aParameters['sStartList'] = '<ul>';
$aParameters['sEndList'] = '</ul>';
$aParameters['sStartItem'] = '<li>';
$aParameters['sEndItem'] = '</li>';
$aParameters['bLastEndItem'] = true;
}
break;
case 'order':
switch ($sArg) {
case 'ascending':
$aParameters['sOrder'] = 'ascending';
break;
case 'descending':
default:
$aParameters['sOrder'] = 'descending';
}
break;
case 'ordermethod':
switch ($sArg) {
case 'lastedit':
$aParameters['sOrderMethod'] = 'lastedit';
break;
case 'categoryadd':
default:
$aParameters['sOrderMethod'] = 'categoryadd';
}
break;
case 'count':
$aParameters['iCount'] = IntVal( $sArg );
$aParameters['bCountSet'] = true;
break;
case 'suppresserrors':
if ('true' == $sArg) $aParameters['bSuppressErrors'] = true;
else $aParameters['bSuppressErrors'] = false;
break;
case 'redirects':
switch ($sArg) {
case 'include':
$aParameters['sRedirects'] = 'include';
break;
case 'only':
$aParameters['sRedirects'] = 'only';
break;
case 'exclude':
default:
$aParameters['sRedirects'] = 'exclude';
}
break;
case 'addfirstcategorydate':
if ('true' == $sArg) $aParameters['bAddFirstCategoryDate'] = true;
else $aParameters['bAddFirstCategoryDate'] = false;
break;
default:
}
}
// Calculate and check category counts against configuration limits
$aParameters['iCatCount'] = count($aParameters['aCategories']);
$aParameters['iTotalIncludeCatCount'] = count($aParameters['aCategories'], COUNT_RECURSIVE) - $aParameters['iCatCount'];
$aParameters['iExcludeCatCount'] = count($aParameters['aExcludeCategories']);
$aParameters['iTotalCatCount'] = $aParameters['iCatCount'] + $aParameters['iExcludeCatCount'];
// 'DynamicPageList: You need to include at least one category, or specify a namespace!'
if ($aParameters['iCatCount'] < 1 && !count($aParameters['abNamespace'])) {
if (false == $aParameters['bSuppressErrors']) {
return htmlspecialchars( wfMsg( 'dynamicpagelist_noincludecats' ) );
} else return '';
}
// 'DynamicPageList: Too few categories!'
if ($aParameters['iTotalIncludeCatCount'] < $wgDLPminCategories && !count($aParameters['abNamespace'])) {
if (false == $aParameters['bSuppressErrors']) {
echo $aParameters['iTotalIncludeCatCount'], $wgDLPminCategories;
return htmlspecialchars( wfMsg( 'dynamicpagelist_toofewcats' ) );
} else return '';
}
// 'DynamicPageList: Too many categories!'
if ( $aParameters['iTotalCatCount'] > $wgDLPmaxCategories && !$wgDLPAllowUnlimitedCategories ) {
if (false == $aParameters['bSuppressErrors'])
return htmlspecialchars( wfMsg( 'dynamicpagelist_toomanycats' ) );
else return '';
}
// DynamicPageList: You need to include at least one category to use \'addfirstcategorydate=true\' or \'ordermethod=categoryadd\'!
if ( $aParameters['iCatCount'] == 0 && ($aParameters['sOrderMethod'] == 'categoryadd' || $aParameters['bAddFirstCategoryDate'] == true) ) {
if (false == $aParameters['bSuppressErrors'])
return htmlspecialchars( wfMsg( 'dynamicpagelist_noincludedcatsbutcatdate' ) );
else return '';
}
// DynamicPageList: If you include more than one category you cannot use \'addfirstcategorydate=true\' or \'ordermethod=categoryadd\'!
if ($aParameters['iTotalCatCount'] > 1 && ($aParameters['sOrderMethod'] == 'categoryadd' || $aParameters['bAddFirstCategoryDate'] == true) ) {
if (false == $aParameters['bSuppressErrors'])
return htmlspecialchars( wfMsg( 'dynamicpagelist_morethanonecatbutcatdate' ) );
else return '';
}
// DynamicPageList: You need to use \'ordermethod=title\' when using category-style output!
if ($aParameters['sOutputMode'] == 'category' && $aParameters['sOrderMethod'] != 'title') {
if (false == $aParameters['bSuppressErrors'])
return htmlspecialchars( wfMsg( 'dpl2_catoutputwithwrongordermethod' ) );
else return '';
}
if ($aParameters['bCountSet']) {
if ($aParameters['iCount'] < $wgDLPMinResultCount) $aParameters['iCount'] = $wgDLPMinResultCount;
if ($aParameters['iCount'] > $wgDLPMaxResultCount) $aParameters['iCount'] = $wgDLPMaxResultCount;
} else {
if (!$wgDLPAllowUnlimitedResults) {
$aParameters['iCount'] = $wgDLPMaxResultCount;
$aParameters['bCountSet'] = true;
}
}
// prevent display of date when no include category defined
if ($aParameters['iCatCount'] < 1) $aParameters['bAddFirstCategoryDate'] = false;
return $aParameters;
}
/* **
* function: BuildSQL
* **
* Purpose: build the necessary SQL statement for the given parameters
* **
* @return STRING SQL query
* ** */
function BuildSQL ( $aParameters ) {
// Globals
$dbr =& wfGetDB( DB_SLAVE );
//build the SQL query
$sPageTable = $dbr->tableName( 'page' );
$categorylinks = $dbr->tableName( 'categorylinks' );
if ($aParameters['iTotalIncludeCatCount'] == 1)
$sSqlSelectFrom = "SELECT DISTINCT page_namespace, page_touched, page_title, c1.cl_timestamp FROM $sPageTable";
else
$sSqlSelectFrom = "SELECT DISTINCT page_namespace, page_touched, page_title FROM $sPageTable";
// Set the selectfrom
$iCurrentTableNumber = 0;
for ($i = 0; $i < $aParameters['iCatCount']; $i++) {
$sSqlSelectFrom .= " INNER JOIN $categorylinks AS c" . ($iCurrentTableNumber+1);
$sSqlSelectFrom .= ' ON page_id = c'.($iCurrentTableNumber+1).'.cl_from';
$sSqlSelectFrom .= ' AND (c'.($iCurrentTableNumber+1).'.cl_to='. $dbr->addQuotes( $aParameters['aCategories'][$i][0]->getDbKey() );
for ($j = 1; $j < count($aParameters['aCategories'][$i]); $j++) {
$sSqlSelectFrom .= ' OR c' . ($iCurrentTableNumber+1) . '.cl_to=' . $dbr->addQuotes( $aParameters['aCategories'][$i][$j]->getDbKey() );
}
$sSqlSelectFrom .= ') ';
$iCurrentTableNumber++;
}
// if namespace
$i = count($aParameters['abNamespace']);
if ($i > 0) {
$sSqlWhere = ' WHERE (page_namespace=' . $aParameters['aNamespace'][0] . ' ';
if ($i > 1) {
for ($i = 1; $i < count($aParameters['aNamespace']); $i++ ) {
if (true == $aParameters['abNamespace'][$i])
$sSqlWhere .= ' OR page_namespace=' . $aParameters['aNamespace'][$i];
}
}
$sSqlWhere .= ') ';
}
// if only or exclude redirects...
switch ($aParameters['sRedirects']) {
case 'only':
if (isset($sSqlWhere)) $sSqlWhere .= ' AND page_is_redirect = 1 ';
else $sSqlWhere = ' WHERE page_is_redirect = 1 ';
break;
case 'exclude':
if (isset($sSqlWhere)) $sSqlWhere .= ' AND page_is_redirect = 0 ';
else $sSqlWhere = ' WHERE page_is_redirect = 0 ';
break;
}
if (!isset($sSqlWhere)) $sSqlWhere = ' WHERE 1=1 ';
for ($i = 0; $i < $aParameters['iExcludeCatCount']; $i++) {
$sSqlSelectFrom .= " LEFT OUTER JOIN $categorylinks AS c" . ($iCurrentTableNumber+1);
$sSqlSelectFrom .= ' ON page_id = c'.($iCurrentTableNumber+1).'.cl_from';
$sSqlSelectFrom .= ' AND c'.($iCurrentTableNumber+1).'.cl_to='.
$dbr->addQuotes( $aParameters['aExcludeCategories'][$i]->getDbKey() );
$sSqlWhere .= ' AND c'.($iCurrentTableNumber+1).'.cl_to IS NULL';
$iCurrentTableNumber++;
}
// Set the sort method, direction
switch ($aParameters['sOrderMethod']) {
case 'lastedit':
$sSqlWhere .= ' ORDER BY page_touched ';
break;
case 'categoryadd':
$sSqlWhere .= ' ORDER BY c1.cl_timestamp ';
break;
case 'title':
default:
$sSqlWhere .= ' ORDER BY page_title ';
break;
}
if ('descending' == $aParameters['sOrder']) $sSqlWhere .= 'DESC';
else $sSqlWhere .= 'ASC';
// if count parameter set
if ($aParameters['bCountSet']) $sSqlWhere .= ' LIMIT ' . $aParameters['iCount'];
return $sSqlSelectFrom . $sSqlWhere;
}
function processQuery ( $sSql, $aParameters ) {
// Globals
global $wgUser, $wgLang;
$dbr =& wfGetDB( DB_SLAVE );
//DEBUG: output SQL query
$output .= "QUERY: [{$sSql}]<br /><br />";
// process the query
$res = $dbr->query($sSql);
$sk =& $wgUser->getSkin();
// if no results returned
if ($dbr->numRows( $res ) == 0) {
if (false == $aParameters['bSuppressErrors'])
return $output . htmlspecialchars( wfMsg( 'dynamicpagelist_noresults' ) );
else return '';
}
// Display the output
//start list
$output .= $aParameters['sStartList'] . "\n";
//process results of query, outputing equivalent of <li>[[Article]]</li> for each result,
//or something similar if the list uses other startlist/endlist
while ($row = $dbr->fetchObject( $res ) ) {
$title = Title::makeTitle( $row->page_namespace, $row->page_title);
$output .= $aParameters['sStartItem'];
if (true == $aParameters['bAddFirstCategoryDate'])
$output .= $wgLang->date($row->cl_timestamp) . ': ';
if (true == $aParameters['bShowNamespace'])
$output .= $sk->makeKnownLinkObj($title);
else
$output .= $sk->makeKnownLinkObj($title, htmlspecialchars($title->getText()));
$output .= $aParameters['sEndItem'] . "\n";
}
//end unordered list
$output .= $aParameters['sEndList'] . "\n";
return $output;
}
// The callback function for converting the input text to HTML output
function DynamicPageList( $input ) {
// Disable page cache
global $wgTitle;
$dbw =& wfGetDB( DB_MASTER );
$dbw->update( 'page', array( 'page_touched' => $dbw->timestamp( time() + 120 )),
array(
'page_namespace' => $wgTitle->getNamespace(),
'page_title' => $wgTitle->getDBkey()
), 'DynamicPageList'
);
// parse the parameters
$aParameters = setParams( $input );
if (!is_array($aParameters)) return $aParameters;
// build the query
$sSql = BuildSql( $aParameters );
// Get output
$output = processQuery( $sSql, $aParameters );
return $output;
}
?>

File Metadata

Mime Type
text/x-php
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1387
Default Alt Text
DynamicPageList.php (16 KB)

Event Timeline