Difference between revisions of "User:Eclecticdave"
From FollowTheScore
Eclecticdave (talk | contribs) (New page: == Experimental Patch for DPL on MW 1.12 == The patch below is intended to be a "proof of concept" implementation of DPL under MW 1.12's new parser. It is far from feature complete and a...) |
(No difference)
|
Revision as of 00:43, 24 April 2008
Experimental Patch for DPL on MW 1.12
The patch below is intended to be a "proof of concept" implementation of DPL under MW 1.12's new parser. It is far from feature complete and almost certainly has some bugs so user beware ;-)
What you need to know
- Template escaping using ²{ }² is no longer possible, but is unnecessary on the new parser. You will need to remove the escapes. Any templates used in format/listseparators, secseparators, multisecseparators and any of the resultsheader/footer parameters will automatically be deferred and evaluated for each article returned.
- Substitution of tokens like %PAGE%, %COUNT% etc. within embedded templates is also no longer possible. I've implemented an alternative in the form of a new 'dplvar' parser function - use the form instead.
- Due to a quirk in the new parser the first parameter to DPL is evaluated too early for template expansion to be intercepted (see bug 12842). Don't use format/listseparators etc in the first parameter!
- The patched DPL will not run on MW1.11 or earlier.
- Don't apply this patch to a running wiki - please! Re-read the bits about 'experimental' and 'proof of concept' if you find yourself thinking about doing this ;-)
diff --git a/DynamicPageList2.php b/DynamicPageList2.php
index 9371862..81e34c0 100644
--- a/DynamicPageList2.php
+++ b/DynamicPageList2.php
@@ -312,6 +312,8 @@ class ExtDynamicPageList2
private static $allowedNamespaces = NULL; // to be initialized at first use of DPL2, array of all namespaces except Media and Special, because we cannot use the DB for these to generate dynamic page lists.
// Cannot be customized. Use ExtDynamicPageList2::$options['namespace'] or ExtDynamicPageList2::$options['notnamespace'] for customization.
+
+
/**
* Map parameters to possible values.
* A 'default' key indicates the default value for the parameter.
@@ -768,7 +770,7 @@ class ExtDynamicPageList2
//------------------------------ parser #function #dplmatrix:
$wgParser->setFunctionHook( 'dplmatrix', array( __CLASS__, 'dplMatrixParserFunction' ) );
//------------------------------ variant as a parser #function
- $wgParser->setFunctionHook( 'dpl', array( __CLASS__, 'dplParserFunction' ) );
+ $wgParser->setFunctionHook( 'dpl', array( __CLASS__, 'dplParserFunction' ), SFH_OBJECT_ARGS );
// Internationalization file
require_once( 'DynamicPageList2.i18n.php' );
@@ -810,6 +812,7 @@ class ExtDynamicPageList2
$magicWords['dpl'] = array( 0, 'dpl' );
$magicWords['dplchapter'] = array( 0, 'dplchapter' );
$magicWords['dplmatrix'] = array( 0, 'dplmatrix' );
+ $magicWords['dplvar'] = array( 0, 'dplvar' );
# unless we return true, other parser functions extensions won't get loaded.
return true;
}
@@ -851,26 +854,25 @@ class ExtDynamicPageList2
return $parsedDPL;
}
- public static function dplParserFunction(&$parser)
+ public static function dplParserFunction(&$parser, $frame, $arg_list)
{
// callback for the parser function {{#dpl:
$params = array();
$input="";
- $numargs = func_num_args();
+ $numargs = count($arg_list);
if ($numargs < 2) {
$input = "#dpl: no arguments specified";
return str_replace('§','<','§pre>§nowiki>'.$input.'§/nowiki>§/pre>');
}
- // fetch all user-provided arguments (skipping $parser)
- $arg_list = func_get_args();
+ // fetch all user-provided arguments
+ $input .= $arg_list[0] . "\n";
for ($i = 1; $i < $numargs; $i++) {
- $p1 = $arg_list[$i];
- $input .= str_replace("\n","",$p1) ."\n";
+ $input .= trim($frame->expand($arg_list[$i])) . "\n";
}
// for debugging you may want to uncomment the following statement
- // return str_replace('§','<','§pre>§nowiki>'.$input.'§/nowiki>§/pre>');
+ //return str_replace('§','<','§pre>'.$input.'§/pre>');
// $dump1 = self::dumpParsedRefs($parser,"before DPL func");
@@ -878,7 +880,7 @@ class ExtDynamicPageList2
// $dump2 = self::dumpParsedRefs($parser,"after DPL func");
// return $dump1.$text.$dump2;
- return self::dynamicPageList($input, $params, $parser, $reset, 'func');
+ return self::dynamicPageList($arg_list, $frame, $params, $parser, $reset, 'func');
}
public static function dplChapterParserFunction(&$parser, $text='', $heading=' ', $maxLength = -1, $page = '?page?', $link = 'default', $trim=false ) {
@@ -960,6 +962,8 @@ class ExtDynamicPageList2
}
}
+
+
private static function dumpParsedRefs($parser,$label) {
if (!preg_match("/Query Q/",$parser->mTitle->getText())) return '';
$text="\n<pre>$label:\n";
@@ -1037,7 +1041,7 @@ class ExtDynamicPageList2
}
// The real callback function for converting the input text to HTML output
- private static function dynamicPageList( $input, $params, &$parser, &$bReset, $calledInMode ) {
+ private static function dynamicPageList( &$arg_list, &$frame, $params, &$parser, &$bReset, $calledInMode ) {
error_reporting(E_ALL);
@@ -1177,6 +1181,10 @@ class ExtDynamicPageList2
$aMultiSecSeparators = explode(',', self::$options['multisecseparators']['default']);
$iDominantSection = self::$options['dominantsection']['default'];
+ $oSecSeparators = NULL;
+ $oMultiSecSeparators = NULL;
+ $oListSeparators = NULL;
+
$_sOffset = self::$options['offset']['default'];
$iOffset = ($_sOffset == '') ? 0: intval($_sOffset);
@@ -1258,6 +1266,7 @@ class ExtDynamicPageList2
// ###### PARSE PARAMETERS ######
// we replace double angle brackets by < > ; thus we avoid premature tag expansion in the input
+ /*
$input = str_replace('»','>',$input);
$input = str_replace('«','<',$input);
@@ -1270,6 +1279,7 @@ class ExtDynamicPageList2
$input = str_replace('}²','}}',$input);
$aParams = explode("\n", $input);
+ */
$bIncludeUncat = false; // to check if pseudo-category of Uncategorized pages is included
// version 0.9:
@@ -1278,14 +1288,26 @@ class ExtDynamicPageList2
// parse the result recursively. This allows to build complex structures in the output
// which are only understood by the parser if seen as a whole
- foreach($aParams as $iParam => $sParam) {
- $aParam = explode('=', $sParam, 2);
+ foreach($arg_list as $arg) {
+ // The first argument is always pre-parsed, as part of finding out it starts with '#dpl:'.
+ if (is_string($arg)) {
+ $aParam = explode('=', $arg, 2);
if( count( $aParam ) < 2 ) {
- if (trim($aParam[0])!='') $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, $aParam[0]. " [missing '=']", implode(', ', array_keys(self::$options)));
+ if (trim($aParam[0])!='')
+ $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, $aParam[0]. " [missing '=']",
+ implode(', ', array_keys(self::$options)));
continue;
}
$sType = trim($aParam[0]);
$sArg = trim($aParam[1]);
+ $oArg = NULL;
+ }
+ else {
+ $aParam = $arg->splitArg();
+ $sType = trim($aParam{'name'}->node->nodeValue);
+ $oArg = $aParam{'value'};
+ $sArg = trim($frame->expand($oArg));
+ }
if( $sType=='') {
$output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, '[empty string]', implode(', ', array_keys(self::$options)));
@@ -1935,6 +1957,7 @@ class ExtDynamicPageList2
$sArg = str_replace( '\n', "\n", $sArg );
$sArg = str_replace( "¶", "\n", $sArg ); // the paragraph delimiter is utf8-escaped
$aListSeparators = explode (',', $sArg, 4);
+ $oListSeparators = $oArg;
// mode=userformat will be automatically assumed
$sPageListMode='userformat';
$sInlTxt = '';
@@ -1945,6 +1968,7 @@ class ExtDynamicPageList2
$sArg = str_replace( '\n', "\n", $sArg );
$sArg = str_replace( "¶", "\n", $sArg ); // the paragraph delimiter is utf8-escaped
$aSecSeparators = explode (',',$sArg);
+ $oSecSeparators = $oArg;
break;
case 'multisecseparators':
@@ -1952,6 +1976,7 @@ class ExtDynamicPageList2
$sArg = str_replace( '\n', "\n", $sArg );
$sArg = str_replace( "¶", "\n", $sArg ); // the paragraph delimiter is utf8-escaped
$aMultiSecSeparators = explode (',',$sArg);
+ $oMultiSecSeparators = $oArg;
break;
case 'table':
@@ -2015,21 +2040,27 @@ class ExtDynamicPageList2
break;
case 'resultsheader':
$sResultsHeader = $sArg;
+ $oResultsHeader = $oArg;
break;
case 'resultsfooter':
$sResultsFooter = $sArg;
+ $oResultsFooter = $oArg;
break;
case 'noresultsheader':
$sNoResultsHeader = $sArg;
+ $oNoResultsHeader = $oArg;
break;
case 'noresultsfooter':
$sNoResultsFooter = $sArg;
+ $oNoResultsFooter = $oArg;
break;
case 'oneresultheader':
$sOneResultHeader = $sArg;
+ $oOneResultHeader = $oArg;
break;
case 'oneresultfooter':
$sOneResultFooter = $sArg;
+ $oOneResultFooter = $oArg;
break;
/**
@@ -2244,6 +2275,8 @@ class ExtDynamicPageList2
// if 'table' parameter is set: derive values for listseparators, secseparators and multisecseparators
$defaultTemplateSuffix='.default';
if ($sTable!='') {
+ $oSecSeparators = NULL;
+ $oMultiSecSeparators = NULL;
$defaultTemplateSuffix='';
$sPageListMode='userformat';
$sInlTxt = '';
@@ -2288,7 +2321,9 @@ class ExtDynamicPageList2
$sSqlPage_size = '';
$sSqlPage_touched = '';
$sSqlCalcFoundRows = '';
- if ( isset($iCount) && $sGoal != 'categories' && strpos($sResultsHeader.$sResultsFooter,'%TOTALPAGES%')!==false) $sSqlCalcFoundRows = 'SQL_CALC_FOUND_ROWS';
+ // Can't figure out a way of checking if TOTALPAGES is used on new parser/syntax
+ //if ( isset($iCount) && $sGoal != 'categories' && strpos($sResultsHeader.$sResultsFooter,'%TOTALPAGES%')!==false) $sSqlCalcFoundRows = 'SQL_CALC_FOUND_ROWS';
+ if ( isset($iCount) && $sGoal != 'categories' ) $sSqlCalcFoundRows = 'SQL_CALC_FOUND_ROWS';
if ($sDistinctResultSet == 'false') $sSqlDistinct = '';
else $sSqlDistinct = 'DISTINCT';
$sSqlGroupBy = '';
@@ -2829,6 +2864,9 @@ class ExtDynamicPageList2
}
if ($dbr->numRows( $res ) <= 0) {
+ if (isset($oNoResultsHeader)) $sNoResultsHeader = trim($frame->expand($oNoResultsHeader));
+ if (isset($oNoResultsFooter)) $sNoResultsFooter = trim($frame->expand($oNoResultsFooter));
+
if ($sNoResultsHeader != '') $output .= str_replace( '\n', "\n", str_replace( "¶", "\n", $sNoResultsHeader));
if ($sNoResultsFooter != '') $output .= str_replace( '\n', "\n", str_replace( "¶", "\n", $sNoResultsFooter));
if ($sNoResultsHeader == '' && $sNoResultsFooter == '') $output .= $logger->escapeMsg(DPL2_i18n::WARN_NORESULTS);
@@ -3021,10 +3059,12 @@ class ExtDynamicPageList2
// ###### SHOW OUTPUT ######
$listMode = new DPL2ListMode($sPageListMode, $aSecSeparators, $aMultiSecSeparators, $sInlTxt, $sListHtmlAttr,
- $sItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
+ $sItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection,
+ $oSecSeparators, $oMultiSecSeparators, $oListSeparators, $frame);
$hListMode = new DPL2ListMode($sHListMode, $aSecSeparators, $aMultiSecSeparators, '', $sHListHtmlAttr,
- $sHItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
+ $sHItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection,
+ $oSecSeparators, $oMultiSecSeparators, $oListSeparators, $frame);
$dpl = new DPL2($aHeadings, $bHeadingCount, $iColumns, $iRows, $iRowSize, $sRowColFormat, $aArticles,
$aOrderMethods[0], $hListMode, $listMode, $bEscapeLinks, $bIncPage, $iIncludeMaxLen,
@@ -3032,8 +3072,18 @@ class ExtDynamicPageList2
$iTitleMaxLen, $defaultTemplateSuffix, $aTableRow, $bIncludeTrim);
if ($rowcount == -1) $rowcount = $dpl->getRowCount();
+ $dpl->setTotalRows($rowcount);
$dpl2result = $dpl->getText();
$header='';
+
+ // Re-evaluate templates
+ if (isset($oOneResultHeader)) $sOneResultHeader = trim($frame->expand($oOneResultHeader));
+ if (isset($oOneResultFooter)) $sOneResultFooter = trim($frame->expand($oOneResultFooter));
+ if (isset($oNoResultsHeader)) $sNoResultsHeader = trim($frame->expand($oNoResultsHeader));
+ if (isset($oNoResultsFooter)) $sNoResultsFooter = trim($frame->expand($oNoResultsFooter));
+ if (isset($oResultsHeader)) $sResultsHeader = trim($frame->expand($oResultsHeader));
+ if (isset($oResultsFooter)) $sResultsFooter = trim($frame->expand($oResultsFooter));
+
if ($sOneResultHeader != '' && $rowcount==1) {
$header = str_replace('%PAGES%',1,$sOneResultHeader);
} else if ($rowcount==0) {
@@ -3253,9 +3303,14 @@ class DPL2ListMode {
var $sSectionTags = array();
var $aMultiSecSeparators = array();
var $iDominantSection = -1;
+ var $oSecSeparators = NULL;
+ var $oMultiSecSeparators = NULL;
+ var $oListSeparators = NULL;
+ var $frame = NULL;
function DPL2ListMode($listmode, $secseparators, $multisecseparators, $inlinetext, $listattr = '', $itemattr = '',
- $listseparators, $iOffset, $dominantSection) {
+ $listseparators, $iOffset, $dominantSection,
+ $oSecSeparators, $oMultiSecSeparators, $oListSeparators, $frame) {
// default for inlinetext (if not in mode=userformat)
if (($listmode != 'userformat') && ($inlinetext == ''))
$inlinetext = ' - ';
@@ -3265,6 +3320,10 @@ class DPL2ListMode {
$this->sSectionTags = $secseparators;
$this->aMultiSecSeparators = $multisecseparators;
+ $this->oSecSeparators = $oSecSeparators;
+ $this->oMultiSecSeparators = $oMultiSecSeparators;
+ $this->oListSeparators = $oListSeparators;
+ $this->frame = $frame;
$this->iDominantSection = $dominantSection - 1; // 0 based index
switch ($listmode) {
@@ -3325,12 +3384,14 @@ class DPL2ListMode {
class DPL2 {
+ private static $totalRows = 0;
+ private static $article = NULL;
+ private static $mEscapeLinks; // whether to escape img/cat or not
var $mArticles;
var $mHeadingType; // type of heading: category, user, etc. (depends on 'ordermethod' param)
var $mHListMode; // html list mode for headings
var $mListMode; // html list mode for pages
- var $mEscapeLinks; // whether to escape img/cat or not
var $mIncPage; // true only if page transclusion is enabled
var $mIncMaxLen; // limit for text to include
var $mIncSecLabels = array(); // array of labels of sections to transclude
@@ -3347,15 +3408,61 @@ class DPL2 {
var $nameSpaces;
var $mTableRow; // formatting rules for table fields
+ public static function dplVarParserFunction(&$parser, $name) {
+ $arg_list = func_get_args();
+
+ if (strcasecmp($name, 'PAGE') == 0) {
+ $pagename = self::$article->mTitle->getPrefixedText();
+ if (self::$mEscapeLinks && (self::$article->mNamespace==14 || self::$article->mNamespace==6) ) {
+ // links to categories or images need an additional ":"
+ $pagename = ':'.$pagename;
+ }
+ return $pagename;
+ }
+ if (strcasecmp($name, 'TITLE') == 0) {
+ $title = self::$article->mTitle->getText();
+ // TODO
+ //if (strpos($title,'%TITLE')>=0) {
+ // if ($this->mReplaceInTitle[0]!='') $title = preg_replace($this->mReplaceInTitle[0],$this->mReplaceInTitle[1],$title);
+ // if( isset($titleMaxLength) && (strlen($title) > $titleMaxLength)) $title = substr($title, 0, $titleMaxLength) . '...';
+ //}
+ return $title;
+ }
+ if (strcasecmp($name, 'PAGES') == 0) {
+ return self::$totalRows;
+ }
+ if (strcasecmp($name, 'TOTALPAGES') == 0) {
+ return self::$totalRows;
+ }
+ if (strcasecmp($name, 'VERSION') == 0) {
+ return self::VERSION;
+ }
+ // Can't just put commas in here because listseparators/format also
+ // uses them and its all parsed in one big lump in the new parser
+ // So, we use a special escape \c and replace it later.
+ if (strcasecmp($name, 'CATLIST') == 0) {
+ return implode('\c', self::$article->mCategoryLinks);
+ }
+ if (strcasecmp($name, 'CATNAMES') == 0) {
+ return implode('\c', self::$article->mCategoryTexts);
+ }
+
+ // If we get here, just return the value 180 for now.
+ return "180";
+ }
+
function DPL2($headings, $bHeadingCount, $iColumns, $iRows, $iRowSize, $sRowColFormat, $articles, $headingtype, $hlistmode,
$listmode, $bescapelinks, $includepage, $includemaxlen, $includeseclabels, $includeseclabelsmatch,
$includeseclabelsnotmatch, $includematchparsed, &$parser, $logger, $replaceInTitle, $iTitleMaxLen,
$defaultTemplateSuffix, $aTableRow, $bIncludeTrim ) {
- global $wgContLang;
+ global $wgContLang, $wgParser;
+
+ $wgParser->setFunctionHook( 'dplvar', array( __CLASS__, 'dplVarParserFunction' ) );
+
$this->nameSpaces = $wgContLang->getNamespaces();
$this->mArticles = $articles;
$this->mListMode = $listmode;
- $this->mEscapeLinks = $bescapelinks;
+ self::$mEscapeLinks = $bescapelinks;
$this->mIncPage = $includepage;
if($includepage) {
$this->mIncSecLabels = $includeseclabels;
@@ -3560,8 +3667,45 @@ class DPL2 {
// the following statement caused a problem with multiple columns: $this->filteredCount = 0;
for ($i = $iStart; $i < $iStart+$iCount; $i++) {
$article = $this->mArticles[$i];
+
+ self::$article = &$article;
+ if (isset($mode->oSecSeparators))
+ $mode->aSecSeparators = explode(',', $mode->frame->expand($mode->oSecSeparators));
+ if (isset($mode->oMultiSecSeparators))
+ $mode->aMultiSecSeparators = explode(',', $mode->frame->expand($mode->oMultiSecSeparators));
+ if (isset($mode->oListSeparators))
+ $mode->aListSeparators = explode(',', $mode->frame->expand($mode->oListSeparators));
+
+ // Convert newlines, plus \c escapes used in CATLIST and CATNAMES
+ switch(count($mode->aListSeparators)) {
+ case 4:
+ $mode->aListSeparators[3] = str_replace( '\n', "\n", str_replace( "¶", "\n", $mode->aListSeparators[3] ));
+ $mode->aListSeparators[3] = str_replace( '\c', ", ", $mode->aListSeparators[3] );
+ case 3:
+ $mode->aListSeparators[2] = str_replace( '\n', "\n", str_replace( "¶", "\n", $mode->aListSeparators[2] ));
+ $mode->aListSeparators[2] = str_replace( '\c', ", ", $mode->aListSeparators[2] );
+ case 2:
+ $mode->aListSeparators[1] = str_replace( '\n', "\n", str_replace( "¶", "\n", $mode->aListSeparators[1] ));
+ $mode->aListSeparators[1] = str_replace( '\c', ", ", $mode->aListSeparators[1] );
+ case 1:
+ $mode->aListSeparators[0] = str_replace( '\n', "\n", str_replace( "¶", "\n", $mode->aListSeparators[0] ));
+ $mode->aListSeparators[0] = str_replace( '\c', ", ", $mode->aListSeparators[0] );
+ }
+
+ /* Taken from DPLListMode ... */
+ switch(count($mode->aListSeparators)) {
+ case 4:
+ $mode->sListEnd = $mode->aListSeparators[3];
+ case 3:
+ $mode->sItemEnd = $mode->aListSeparators[2];
+ case 2:
+ $mode->sItemStart = $mode->aListSeparators[1];
+ case 1:
+ $mode->sListStart = $mode->aListSeparators[0];
+ }
+
$pagename = $article->mTitle->getPrefixedText();
- if ($this->mEscapeLinks && ($article->mNamespace==14 || $article->mNamespace==6) ) {
+ if (self::$mEscapeLinks && ($article->mNamespace==14 || $article->mNamespace==6) ) {
// links to categories or images need an additional ":"
$pagename = ':'.$pagename;
}
@@ -3823,6 +3967,10 @@ class DPL2 {
return $this->filteredCount;
}
+ function setTotalRows($rowcount) {
+ self::$totalRows = $rowcount;
+ }
+
//cut wiki text around lim
function cutAt($lim,$text) {
if ($lim<0) return $text;
@@ -3958,4 +4106,4 @@ class DPL2Logger {
}
-?>
\ No newline at end of file
+?>