r17527 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r17526‎ | r17527 | r17528 >
Date:22:04, 10 November 2006
Author:cdangerville
Status:old
Tags:
Comment:
Release 0.7.8
* addpagecounter feature (adds # times page has been viewed)
* 'ordermethod = counter' feature: orders pages by #times page has been viewed
* Fixed bug: encode page_title in utf8 in sql query before string concat that generates sortkey
* Refactoring with creation of classes: DPL2 in charge of the list output, DPL2Article stores the relevant article attributes for DPL
* Improved the generation of links.
* Modified/renamed DPL2UpdateLinks() method
* Added options parse, parsemag and escape to method msgExt(), taking wfMsgExt as a model
Modified paths:
  • /trunk/extensions/DynamicPageList2/DynamicPageList2.php (modified) (history)

Diff [purge]

Index: trunk/extensions/DynamicPageList2/DynamicPageList2.php
@@ -19,13 +19,13 @@
2020 * @author w:de:Benutzer:Unendlich
2121 * @author m:User:Dangerman <cyril.dangerville@gmail.com>
2222 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
23 - * @version 0.7.7
 23+ * @version 0.7.8
2424 */
2525
2626 /*
2727 * Current version
2828 */
29 -define('DPL2_VERSION', '0.7.7');
 29+define('DPL2_VERSION', '0.7.8');
3030
3131 /**
3232 * Register the extension with MediaWiki
@@ -58,6 +58,7 @@
5959 */
6060 $wgDPL2Options = array(
6161 'addcategories' => array('default' => 'false', 'false', 'true'),
 62+ 'addpagecounter' => array('default' => 'false', 'false', 'true'),
6263 'addeditdate' => array('default' => 'false', 'false', 'true'),
6364 'addfirstcategorydate' => array('default' => 'false', 'false', 'true'),
6465 'addpagetoucheddate' => array('default' => 'false', 'false', 'true'),
@@ -165,7 +166,7 @@
166167 * 'ordermethod=param1,param2' means ordered by param1 first, then by param2.
167168 * @todo: add 'ordermethod=category,categoryadd' (for each category CAT, pages ordered by date when page was added to CAT).
168169 */
169 - 'ordermethod' => array('default' => 'title', 'category,firstedit', 'category,lastedit', 'category,pagetouched', 'category,sortkey', 'categoryadd', 'firstedit', 'lastedit', 'pagetouched', 'title', 'user,firstedit', 'user,lastedit'),
 170+ 'ordermethod' => array('default' => 'title', 'counter', 'category,firstedit', 'category,lastedit', 'category,pagetouched', 'category,sortkey', 'categoryadd', 'firstedit', 'lastedit', 'pagetouched', 'title', 'user,firstedit', 'user,lastedit'),
170171 /**
171172 * minoredits =... (compatible with ordermethod=...,firstedit | lastedit only)
172173 * - exclude: ignore minor edits when sorting the list (rev_minor_edit = 0 only)
@@ -275,13 +276,14 @@
276277 // Options
277278 $aOrderMethods = explode(',', $wgDPL2Options['ordermethod']['default']);
278279 $sOrder = $wgDPL2Options['order']['default'];
279 - $sPageOutputMode = $wgDPL2Options['mode']['default'];
280 - $sHeadingOutputMode = $wgDPL2Options['headingmode']['default'];
 280+ $sPageListMode = $wgDPL2Options['mode']['default'];
 281+ $sHListMode = $wgDPL2Options['headingmode']['default'];
281282 $sMinorEdits = NULL;
282283 $sRedirects = $wgDPL2Options['redirects']['default'];
283284 $sInlTxt = $wgDPL2Options['inlinetext']['default'];
284285 $bShowNamespace = $wgDPL2Options['shownamespace']['default'] == 'true';
285286 $bAddFirstCategoryDate = $wgDPL2Options['addfirstcategorydate']['default'] == 'true';
 287+ $bAddPageCounter = $wgDPL2Options['addpagecounter']['default'] == 'true';
286288 $bAddPageTouchedDate = $wgDPL2Options['addpagetoucheddate']['default'] == 'true';
287289 $bAddEditDate = $wgDPL2Options['addeditdate']['default'] == 'true';
288290 $bAddUser = $wgDPL2Options['adduser']['default'] == 'true';
@@ -430,6 +432,13 @@
431433 $output .= $logger->msgWrongParam('addfirstcategorydate', $sArg);
432434 break;
433435
 436+ case 'addpagecounter':
 437+ if( in_array($sArg, $wgDPL2Options['addpagecounter']))
 438+ $bAddPageCounter = $sArg == 'true';
 439+ else
 440+ $output .= $logger->msgWrongParam('addpagecounter', $sArg);
 441+ break;
 442+
434443 case 'addpagetoucheddate':
435444 if( in_array($sArg, $wgDPL2Options['addpagetoucheddate']))
436445 $bAddPageTouchedDate = $sArg == 'true';
@@ -467,7 +476,7 @@
468477 */
469478 case 'headingmode':
470479 if( in_array($sArg, $wgDPL2Options['headingmode']) )
471 - $sHeadingOutputMode = $sArg;
 480+ $sHListMode = $sArg;
472481 else
473482 $output .= $logger->msgWrongParam('headingmode', $sArg);
474483 break;
@@ -476,10 +485,10 @@
477486 if( in_array($sArg, $wgDPL2Options['mode']) )
478487 //'none' mode is implemented as a specific submode of 'inline' with <BR/> as inline text
479488 if($sArg == 'none') {
480 - $sPageOutputMode = 'inline';
 489+ $sPageListMode = 'inline';
481490 $sInlTxt = '<BR/>';
482491 } else
483 - $sPageOutputMode = $sArg;
 492+ $sPageListMode = $sArg;
484493 else
485494 $output .= $logger->msgWrongParam('mode', $sArg);
486495 break;
@@ -566,7 +575,7 @@
567576 return $logger->msg(DPL2_ERR_MORETHAN1TYPEOFDATE);
568577
569578 // category-style output requested with not compatible order method
570 - if ($sPageOutputMode == 'category' && !array_intersect($aOrderMethods, array('sortkey', 'title')) )
 579+ if ($sPageListMode == 'category' && !array_intersect($aOrderMethods, array('sortkey', 'title')) )
571580 return $logger->msg(DPL2_ERR_WRONGORDERMETHOD, 'mode=category', 'sortkey | title' );
572581
573582 // addpagetoucheddate=true with unappropriate order methods
@@ -611,13 +620,13 @@
612621 }
613622
614623 //add*** parameters have no effect with 'mode=category' (only namespace/title can be viewed in this mode)
615 - if( $sPageOutputMode == 'category' && ($bAddCategories || $bAddEditDate || $bAddFirstCategoryDate || $bAddPageTouchedDate || $bAddUser) )
 624+ if( $sPageListMode == 'category' && ($bAddCategories || $bAddEditDate || $bAddFirstCategoryDate || $bAddPageTouchedDate || $bAddUser) )
616625 $output .= $logger->msg(DPL2_WARN_CATOUTPUTBUTWRONGPARAMS);
617626
618627 //headingmode has effects with ordermethod on multiple components only
619 - if( $sHeadingOutputMode != 'none' && count($aOrderMethods) < 2 ) {
620 - $output .= $logger->msg(DPL2_WARN_HEADINGBUTSIMPLEORDERMETHOD, $sHeadingOutputMode, 'none');
621 - $sHeadingOutputMode = 'none';
 628+ if( $sHListMode != 'none' && count($aOrderMethods) < 2 ) {
 629+ $output .= $logger->msg(DPL2_WARN_HEADINGBUTSIMPLEORDERMETHOD, $sHListMode, 'none');
 630+ $sHListMode = 'none';
622631 }
623632
624633 // justify limits
@@ -629,6 +638,7 @@
630639
631640
632641 // ###### BUILD SQL QUERY ######
 642+ $sSqlPage_counter = '';
633643 $sSqlPage_touched = '';
634644 $sSqlSortkey = '';
635645 $sSqlCl_to = '';
@@ -653,7 +663,7 @@
654664 switch ($sOrderMethod) {
655665 case 'category':
656666 $sSqlCl_to = "cl_head.cl_to, "; // Gives category headings in the result
657 - $sSqlClHeadTable = ( in_array('', $aCatHeadings) ? $sDplClView : $sCategorylinksTable ) . ' AS cl_head';
 667+ $sSqlClHeadTable = ( in_array('', $aCatHeadings) ? $sDplClView : $sCategorylinksTable ) . ' AS cl_head'; // use dpl_clview if Uncategorized in headings
658668 $sSqlCond_page_cl_head = 'page_id=cl_head.cl_from';
659669 if(!empty($aCatHeadings))
660670 $sSqlWhere .= " AND cl_head.cl_to IN ('" . implode("', '", $aCatHeadings) . "')";
@@ -677,7 +687,7 @@
678688 $sSqlNsIdToText .= ' WHEN ' . $iNs . " THEN '" . $sNs . "'";
679689 $sSqlNsIdToText .= ' END';
680690 // If cl_sortkey is null (uncategorized page), generate a sortkey in the usual way (full page name, underscores replaced with spaces).
681 - $sSqlSortkey = ", IFNULL(cl_head.cl_sortkey, REPLACE(CONCAT( IF(page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), page_title), '_', ' ')) as sortkey";
 691+ $sSqlSortkey = ", IFNULL(cl_head.cl_sortkey, REPLACE(CONCAT( IF(page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), CONVERT(page_title USING utf8)), '_', ' ')) as sortkey";
682692 break;
683693 case 'title':
684694 $aStrictNs = array_slice($wgDPL2AllowedNamespaces, 1, count($wgDPL2AllowedNamespaces), true);
@@ -687,10 +697,11 @@
688698 $sSqlNsIdToText .= ' WHEN ' . $iNs . " THEN '" . $sNs . "'";
689699 $sSqlNsIdToText .= ' END';
690700 // Generate sortkey like for category links.
691 - $sSqlSortkey = ", REPLACE(CONCAT( IF(page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), page_title), '_', ' ') as sortkey";
 701+ $sSqlSortkey = ", REPLACE(CONCAT( IF(page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), CONVERT(page_title USING utf8)), '_', ' ') as sortkey";
692702 break;
693703 case 'user':
694704 $sSqlRevisionTable = $sRevisionTable . ', ';
 705+ $sSqlRev_user = ', rev_user, rev_user_text';
695706 break;
696707 }
697708 }
@@ -704,6 +715,8 @@
705716 //format cl_timestamp field (type timestamp) to string in same format as rev_timestamp field
706717 //to make it compatible with $wgLang->date() function used in function DPL2OutputListStyle() to show "firstcategorydate"
707718 $sSqlCl_timestamp = ", DATE_FORMAT(cl0.cl_timestamp, '%Y%m%d%H%i%s') AS cl_timestamp";
 719+ if ($bAddPageCounter)
 720+ $sSqlPage_counter = ', page_counter';
708721 if ($bAddPageTouchedDate)
709722 $sSqlPage_touched = ', page_touched';
710723 if ($bAddUser)
@@ -716,7 +729,7 @@
717730 }
718731
719732 // SELECT ... FROM
720 - $sSqlSelectFrom = 'SELECT DISTINCT ' . $sSqlCl_to . 'page_namespace, page_title' . $sSqlSortkey . $sSqlPage_touched . $sSqlRev_timestamp . $sSqlRev_user . $sSqlCats . $sSqlCl_timestamp . ' FROM ' . $sSqlRevisionTable . $sSqlPageLinksTable . $sPageTable;
 733+ $sSqlSelectFrom = 'SELECT DISTINCT ' . $sSqlCl_to . 'page_namespace, page_title' . $sSqlSortkey . $sSqlPage_counter . $sSqlPage_touched . $sSqlRev_user . $sSqlRev_timestamp . $sSqlCats . $sSqlCl_timestamp . ' FROM ' . $sSqlRevisionTable . $sSqlPageLinksTable . $sPageTable;
721734
722735 // JOIN ...
723736 if($sSqlClHeadTable != '' || $sSqlClTableForGC != '') {
@@ -787,6 +800,9 @@
788801 case 'categoryadd':
789802 $sSqlWhere .= 'cl0.cl_timestamp';
790803 break;
 804+ case 'counter':
 805+ $sSqlWhere .= 'page_counter';
 806+ break;
791807 case 'firstedit':
792808 case 'lastedit':
793809 $sSqlWhere .= 'rev_timestamp';
@@ -818,7 +834,7 @@
819835 // ###### PROCESS SQL QUERY ######
820836 //DEBUG: output SQL query
821837 $output .= $logger->msg(DPL2_QUERY, $sSqlSelectFrom . $sSqlWhere);
822 - // echo 'QUERY: [' . $sSqlSelectFrom . $sSqlWhere . "]<br />";
 838+ //echo 'QUERY: [' . $sSqlSelectFrom . $sSqlWhere . "]<br />";
823839
824840 $res = $dbr->query($sSqlSelectFrom . $sSqlWhere);
825841 if ($dbr->numRows( $res ) == 0) {
@@ -832,50 +848,19 @@
833849 $sSpecUncatLnk = $sk->makeKnownLinkObj( $tSpecUncat, wfMsg('uncategorizedpages') );
834850 // generate title for Special:Contributions (used if adduser=true)
835851 $tSpecContribs = Title::makeTitle( NS_SPECIAL, 'Contributions' );
836 -
837852 // linkBatch used to check the existence of titles
838853 $linkBatch = new LinkBatch();
839 - $aHeadings = array();
840 - //heading titles to be checked by $linkBatch for existence (id in $aHeadings => title)
 854+ $aHeadings = array(); // maps heading to count (# of pages under each heading)
 855+ //heading titles to be checked by $linkBatch for existence
841856 $aUncheckedHeadingTitles = array();
842857 $aArticles = array();
843 - $aArticles_start_char =array();
844 - $aAddDates = array();
845 - $aAddUsers = array();
846 - //user titles to be checked by $linkBatch for existence (id in $aAddUsers => title)
 858+ //user titles to be checked by $linkBatch for existence
847859 $aUncheckedUserTitles = array();
848 - $aAddCategories = array();
849 - //category titles to be checked by $linkBatch for existence (id in $aAddCategories => (id' in $aAddCategories[id] => title))
 860+ //category titles to be checked by $linkBatch for existence
850861 $aUncheckedCatTitles = array();
 862+
851863 $iArticle = 0;
852864 while( $row = $dbr->fetchObject ( $res ) ) {
853 - //HEADINGS (category,... or user,... ordermethods)
854 - if($sHeadingOutputMode != 'none')
855 - switch($aOrderMethods[0]) {
856 - case 'category':
857 - if($row->cl_to == '') //uncategorized page
858 - $aHeadings[] = $sSpecUncatLnk;
859 - else {
860 - $tCat = Title::makeTitle(NS_CATEGORY, $row->cl_to);
861 - //The category title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
862 - $linkBatch->addObj($tCat);
863 - $aUncheckedHeadingTitles[$iArticle] = $tCat;
864 - $aHeadings[] = NULL;
865 - }
866 - break;
867 - case 'user':
868 - if($row->rev_user == 0) //anonymous user
869 - $aHeadings[] = $sk->makeKnownLinkObj($tSpecContribs, $wgContLang->convertHtml($row->rev_user_text), 'target=' . $row->rev_user_text);
870 - else {
871 - $tUser = Title::makeTitle( NS_USER, $row->rev_user_text );
872 - //The user title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
873 - $linkBatch->addObj($tUser);
874 - $aUncheckedHeadingTitles[$iArticle] = $tUser;
875 - $aHeadings[] = NULL;
876 - }
877 - break;
878 - }
879 -
880865 //PAGE LINK
881866 $title = Title::makeTitle($row->page_namespace, $row->page_title);
882867 $sTitleText = $title->getText();
@@ -884,223 +869,137 @@
885870 $sTitleText = substr($sTitleText, 0, $iTitleMaxLen) . '...';
886871 if ($bShowNamespace)
887872 //Adapted from Title::getPrefixedText()
888 - $sTitleText = str_replace( '_', ' ', $title->prefix($sTitleText) );
889 - $aArticles[] = $sk->makeKnownLinkObj($title, $wgContLang->convertHtml($sTitleText));
 873+ $sTitleText = str_replace( '_', ' ', $title->prefix($sTitleText) );
 874+ $articleLink = $sk->makeKnownLinkObj( $title, htmlspecialchars( $wgContLang->convert( $sTitleText ) ) );
 875+ $dplArticle = new DPL2Article( $articleLink );
890876
891877 //get first char used for category-style output
892878 if( isset($row->sortkey) )
893 - $aArticles_start_char[] = $wgContLang->convert($wgContLang->firstChar($row->sortkey));
 879+ $dplArticle->mStartChar = $wgContLang->convert($wgContLang->firstChar($row->sortkey));
894880
 881+ //SHOW PAGE_COUNTER
 882+ if( isset($row->page_counter) )
 883+ $dplArticle->mCounter = $row->page_counter;
 884+
895885 //SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE
896886 if($bAddPageTouchedDate)
897 - $aAddDates[] = $row->page_touched;
 887+ $dplArticle->mDate = $row->page_touched;
898888 elseif ($bAddFirstCategoryDate)
899 - $aAddDates[] = $row->cl_timestamp;
900 - elseif ($bAddEditDate)
901 - $aAddDates[] = $row->rev_timestamp;
902 - else
903 - $aAddDates[] = '';
 889+ $dplArticle->mDate = $row->cl_timestamp;
 890+ elseif ($bAddEditDate)
 891+ $dplArticle->mDate = $row->rev_timestamp;
904892
905893 //USER/AUTHOR(S)
906894 if($bAddUser)
907 - if($row->rev_user == 0) //not registered users
908 - $aAddUsers[] = $sk->makeKnownLinkObj($tSpecContribs, $row->rev_user_text, 'target=' . $row->rev_user_text);
909 - else {
 895+ // Adapted from Linker::userLink()
 896+ if($row->rev_user == 0) { //anonymous user
 897+ $encName = htmlspecialchars( $row->rev_user_text );
 898+ $dplArticle->mUserLink = $sk->makeKnownLinkObj($tSpecContribs, $encName, 'target=' . urlencode($row->rev_user_text) );
 899+ } else {
910900 $tUser = Title::makeTitle( NS_USER, $row->rev_user_text );
911901 //The user title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
912902 $linkBatch->addObj($tUser);
913903 $aUncheckedUserTitles[$iArticle] = $tUser;
914 - $aAddUsers[] = NULL;
915904 }
916 - else
917 - $aAddUsers[] = '';
918905
919906 //CATEGORY LINKS FROM CURRENT PAGE
920 - if(!$bAddCategories || ($row->cats == ''))
921 - $aAddCategories[] = '';
922 - else {
 907+ if($bAddCategories && ($row->cats != '')) {
923908 $artCatNames = explode(' | ', $row->cats);
924 - $artCatLinks = array();
925909 foreach($artCatNames as $iArtCat => $artCatName) {
926910 $tArtCat = Title::makeTitle(NS_CATEGORY, $artCatName);
927911 //The category title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
928912 $linkBatch->addObj($tArtCat);
929913 $aUncheckedCatTitles[$iArticle][$iArtCat] = $tArtCat;
930 - $artCatLinks[] = NULL;
 914+ $dplArticle->mCategoryLinks[] = NULL; //will be set later after link check
931915 }
932 - $aAddCategories[] = $artCatLinks;
933916 }
934917
 918+ // PARENT HEADING (category of the page, editor (user) of the page, etc. Depends on ordermethod param)
 919+ if($sHListMode != 'none') {
 920+ switch($aOrderMethods[0]) {
 921+ case 'category':
 922+ //count one more page in this heading
 923+ $aHeadings[$row->cl_to] = isset($aHeadings[$row->cl_to]) ? $aHeadings[$row->cl_to] + 1 : 1;
 924+ if($row->cl_to == '') //uncategorized page
 925+ $dplArticle->mParentHLink = $sSpecUncatLnk;
 926+ else {
 927+ $tCat = Title::makeTitle(NS_CATEGORY, $row->cl_to);
 928+ //The category title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
 929+ $linkBatch->addObj($tCat);
 930+ $aUncheckedHeadingTitles[$iArticle] = $tCat;
 931+ }
 932+ break;
 933+ case 'user':
 934+ $aHeadings[$row->rev_user_text] = isset($aHeadings[$row->rev_user_text]) ? $aHeadings[$row->rev_user_text] + 1 : 1;
 935+ // Adapted from Linker::userLink()
 936+ if($row->rev_user == 0) { //anonymous user
 937+ $encName = htmlspecialchars( $row->rev_user_text );
 938+ $dplArticle->mParentHLink = $sk->makeKnownLinkObj($tSpecContribs, $encName, 'target=' . urlencode($row->rev_user_text) );
 939+ } else {
 940+ $tUser = Title::makeTitle( NS_USER, $row->rev_user_text );
 941+ //The user title may not exist. Add title to LinkBatch to check that out and to make link accordingly.
 942+ $linkBatch->addObj($tUser);
 943+ $aUncheckedHeadingTitles[$iArticle] = $tUser;
 944+ }
 945+ break;
 946+ }
 947+ }
 948+
 949+ $aArticles[] = $dplArticle;
935950 $iArticle++;
936951 }
937952 $dbr->freeResult( $res );
938953
939 - //ckeck titles in $linkBatch and update links accordingly
 954+ //check titles in $linkBatch and update links accordingly
940955 $linkCache = new LinkCache();
941956 $linkBatch->executeInto($linkCache);
942 - DPL2UpdateLinks($aUncheckedHeadingTitles, $linkCache, $aHeadings);
943 - DPL2UpdateLinks($aUncheckedUserTitles, $linkCache, $aAddUsers);
944 - DPL2UpdateLinks($aUncheckedCatTitles, $linkCache, $aAddCategories);
 957+ DPL2UpdateArticleMemberLinks($aUncheckedHeadingTitles, $linkCache, $aArticles, 'mParentHLink');
 958+ DPL2UpdateArticleMemberLinks($aUncheckedUserTitles, $linkCache, $aArticles, 'mUserLink');
 959+ DPL2UpdateArticleMemberLinks($aUncheckedCatTitles, $linkCache, $aArticles, 'mCategoryLinks');
945960
946961 // ###### SHOW OUTPUT ######
947 - $outputMode = new DPL2OutputMode($sPageOutputMode, $sInlTxt, $sListHtmlAttr, $sItemHtmlAttr);
948 -
949 - if(!empty($aHeadings)) {
950 - $headingMode = new DPL2OutputMode($sHeadingOutputMode, '', $sHListHtmlAttr, $sHItemHtmlAttr);
951 - $aHeadingCounts = array_count_values($aHeadings); //count articles under each heading
952 - $output .= $headingMode->sStartList;
953 - $headingStart = 0;
954 - foreach($aHeadingCounts as $heading => $headingCount) {
955 - $output .= $headingMode->sStartItem;
956 - $output .= $headingMode->sStartHeading . $heading . $headingMode->sEndHeading;
957 - $output .= DPL2FormatCount($headingCount, $aOrderMethods[0], $localParser, $pOptions, $pTitle);
958 - if ($sPageOutputMode == 'category')
959 - $output .= DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, $headingStart, $headingCount);
960 - else
961 - $output .= DPL2OutputListStyle($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $outputMode, $headingStart, $headingCount);
962 - $output .= $headingMode->sEndItem;
963 - $headingStart += $headingCount;
964 - }
965 - $output .= $headingMode->sEndList;
966 - }
967 - elseif($sPageOutputMode == 'category')
968 - $output .= DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, 0, count($aArticles));
969 - else
970 - $output .= DPL2OutputListStyle($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $outputMode, 0, count($aArticles));
971 - return $output;
 962+ $listMode = new DPL2ListMode($sPageListMode, $sInlTxt, $sListHtmlAttr, $sItemHtmlAttr);
 963+ $hListMode = new DPL2ListMode($sHListMode, '', $sHListHtmlAttr, $sHItemHtmlAttr);
 964+ $dpl = new DPL2($aHeadings, $aArticles, $aOrderMethods[0], $hListMode, $listMode, $localParser, $pOptions, $pTitle);
 965+ return $output . $dpl->getText();
972966 }
973967
974968
975 -function DPL2UpdateLinks($aTitles, $linkCache, &$aLinks) {
976 - global $wgUser, $wgContLang;
977 - $sk =& $wgUser->getSkin();
978 - foreach($aTitles as $key => $titleval)
979 - if( is_array($titleval) )
980 - DPL2UpdateLinks($titleval, $linkCache, $aLinks[$key]);
981 - else //$titleval is a single Title object in this case
982 - $aLinks[$key] = $linkCache->isBadLink($titleval->getPrefixedDbKey()) ?
983 - $sk->makeBrokenLinkObj($titleval, $wgContLang->convertHtml($titleval->getText())) :
984 - $sk->makeKnownLinkObj($titleval, $wgContLang->convertHtml($titleval->getText()));
985 -}
986 -
987 -function DPL2OutputListStyle ($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $mode, $iStart, $iCount) {
988 - global $wgUser, $wgLang;
 969+// Simple Article/Page class with properties used in the DPL
 970+class DPL2Article {
 971+ var $mLink = ''; // html link to page
 972+ var $mStartChar = ''; // page title first char
 973+ var $mParentHLink = ''; // heading (link to the associated page) that page belongs to in the list (default '' means no heading)
 974+ var $mCategoryLinks = array(); // category links in the page
 975+ var $mCounter = ''; // Number of times this page has been viewed
 976+ var $mDate = ''; // timestamp depending on the user's request (can be first/last edit, page_touched, ...)
 977+ var $mUserLink = ''; // link to editor (first/last, depending on user's request) 's page or contributions if not registered
989978
990 - $sk = & $wgUser->getSkin();
991 - // generate link to Special:Categories (used if addcategories=true)
992 - $tSpecCats = Title::makeTitle( NS_SPECIAL, 'Categories' );
993 - $sSpecCatsLnk = $sk->makeKnownLinkObj( $tSpecCats, wfMsg('categories'));
994 -
995 - //process results of query, outputing equivalent of <li>[[Article]]</li> for each result,
996 - //or something similar if the list uses other startlist/endlist;
997 - $r = $mode->sStartList;
998 - for ($i = $iStart; $i < $iStart+$iCount; $i++) {
999 - if($i > $iStart)
1000 - $r .= $mode->sInline; //If mode is not 'inline', sInline attribute is empty, so does nothing
1001 - $r .= $mode->sStartItem;
1002 - if($aAddDates[$i] != '')
1003 - $r .= $wgLang->timeanddate($aAddDates[$i], true) . ': ';
1004 - $r .= $aArticles[$i];
1005 - if($aAddUsers[$i] != '')
1006 - $r .= ' . . ' . $aAddUsers[$i];
1007 - if($aAddCategories[$i] != '')
1008 - $r .= ' . . <SMALL>' . $sSpecCatsLnk . ': ' . implode(' | ', $aAddCategories[$i]) . '</SMALL>';
1009 - $r .= $mode->sEndItem;
 979+ function DPL2Article($link) {
 980+ $this->mLink = $link;
1010981 }
1011 - $r .= $mode->sEndList;
1012 - return $r;
1013982 }
1014983
1015 -//slightly different from CategoryPage::formatList() (no need to instantiate a CategoryPage object)
1016 -function DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, $iStart, $iCount) {
1017 - global $wgDPL2CategoryStyleListCutoff;
1018 -
1019 - $subaArticles = array_slice($aArticles, $iStart, $iCount);
1020 - $subaArticles_start_char = array_slice($aArticles_start_char, $iStart, $iCount);
1021 - require_once ('CategoryPage.php');
1022 - if ( count ( $subaArticles ) > $wgDPL2CategoryStyleListCutoff ) {
1023 - return CategoryPage::columnList( $subaArticles, $subaArticles_start_char );
1024 - } elseif ( count($subaArticles) > 0) {
1025 - // for short lists of articles in categories.
1026 - return CategoryPage::shortList( $subaArticles, $subaArticles_start_char );
1027 - }
1028 - return '';
1029 -}
1030984
1031 -function DPL2FormatCount( $numart, $headingtype = '', $parser, $poptions, $ptitle ) {
1032 - global $wgLang;
1033 - if($headingtype == 'category')
1034 - $message = 'categoryarticlecount';
1035 - else
1036 - $message = 'dpl2_articlecount';
1037 - return DPL2MsgExt( $message, $parser, $poptions, $ptitle, $numart);
1038 -}
1039 -
1040 -/**
1041 - * Returns message in the requested format after parsing wikitext to html
1042 - * This is meant to be equivalent to wfMsgExt($key, array('parse')) but using a local parser instead of the global one (bugfix).
1043 - * @param string $key Key of the message
1044 - */
1045 -function DPL2MsgExt( $key, $parser, &$poptions, $ptitle ) {
1046 - $args = func_get_args();
1047 - array_shift( $args );
1048 - array_shift( $args );
1049 - array_shift( $args );
1050 - array_shift( $args );
1051 - $string = wfMsgGetKey( $key, true, false, false );
1052 - $string = wfMsgReplaceArgs( $string, $args );
1053 - $poptions->setInterfaceMessage(true);
1054 - $parserOutput = $parser->parse( $string, $ptitle, $poptions );
1055 - $poptions->setInterfaceMessage(false);
1056 - return $parserOutput->getText();
1057 -}
1058 -
1059 -class DPL2Logger {
1060 - var $iDebugLevel;
1061 -
1062 - function DPL2Logger() {
1063 - global $wgDPL2Options;
1064 - $this->iDebugLevel = $wgDPL2Options['debug']['default'];
1065 - }
1066 -
1067 - function msg($msgid) {
1068 - global $wgDPL2DebugMinLevels;
1069 - if($this->iDebugLevel >= $wgDPL2DebugMinLevels[$msgid]) {
1070 - $args = func_get_args();
1071 - array_shift( $args );
1072 - /**
1073 - * @todo add a DPL id to identify the DPL tag that generates the message, in case of multiple DPLs in the page
1074 - */
1075 - return '%DPL2-' . DPL2_VERSION . '-' . wfMsg('dpl2_debug_' . $msgid, $args) . '<BR/>';
 985+// Updates links in the members (parent heading, category links...) of a DPL2Article according to a LinkCache object
 986+function DPL2UpdateArticleMemberLinks($titles, $linkcache, &$articles, $member) {
 987+ global $wgUser, $wgContLang;
 988+ $sk =& $wgUser->getSkin();
 989+ foreach($titles as $tkey => $titleval) {
 990+ if($member == 'mCategoryLinks') { // $titleval is an array
 991+ foreach($titleval as $catKey => $catTitle) {
 992+ $linkText = htmlspecialchars( $wgContLang->convertHtml($catTitle->getText()) );
 993+ $articles[$tkey]->mCategoryLinks[$catKey] = $linkcache->isBadLink($catTitle->getPrefixedDbKey()) ? $sk->makeBrokenLinkObj($catTitle, $linkText) : $sk->makeKnownLinkObj($catTitle, $linkText);
 994+ }
 995+ } else {
 996+ $linkText = htmlspecialchars( $wgContLang->convertHtml($titleval->getText()) );
 997+ $articles[$tkey]->$member = $linkcache->isBadLink($titleval->getPrefixedDbKey()) ? $sk->makeBrokenLinkObj($titleval, $linkText) : $sk->makeKnownLinkObj($titleval, $linkText);
1076998 }
1077 - return '';
1078999 }
1079 -
1080 - function msgWrongParam($paramvar, $val) {
1081 - global $wgContLang, $wgDPL2Options;
1082 - $msgid = DPL2_WARN_WRONGPARAM;
1083 - switch($paramvar) {
1084 - case 'namespace':
1085 - case 'notnamespace':
1086 - $msgid = DPL2_ERR_WRONGNS;
1087 - break;
1088 - case 'linksto':
1089 - $msgid = DPL2_ERR_WRONGLINKSTO;
1090 - break;
1091 - case 'count':
1092 - case 'titlemaxlength':
1093 - $msgid = DPL2_WARN_WRONGPARAM_INT;
1094 - break;
1095 - }
1096 - $paramoptions = array_unique($wgDPL2Options[$paramvar]);
1097 - sort($paramoptions);
1098 - return $this->msg( $msgid, $paramvar, $val, $wgDPL2Options[$paramvar]['default'], implode(' | ', $paramoptions ));
1099 - }
1100 -
11011000 }
11021001
1103 -
1104 -class DPL2OutputMode {
 1002+
 1003+class DPL2ListMode {
11051004 var $name;
11061005 var $sStartList = '';
11071006 var $sEndList = '';
@@ -1110,12 +1009,12 @@
11111010 var $sEndItem = '';
11121011 var $sInline = '';
11131012
1114 - function DPL2OutputMode($outputmode, $inlinetext = '&nbsp;-&nbsp', $listattr = '', $itemattr = '') {
1115 - $this->name = $outputmode;
 1013+ function DPL2ListMode($listmode, $inlinetext = '&nbsp;-&nbsp', $listattr = '', $itemattr = '') {
 1014+ $this->name = $listmode;
11161015 $_listattr = ($listattr == '') ? '' : ' ' . $listattr;
11171016 $_itemattr = ($itemattr == '') ? '' : ' ' . $itemattr;
11181017
1119 - switch ($outputmode) {
 1018+ switch ($listmode) {
11201019 case 'inline':
11211020 if( stristr($inlinetext, '<BR />') ) { //one item per line (pseudo-inline)
11221021 $this->sStartList = '<DIV'. $_listattr . '>';
@@ -1150,10 +1049,204 @@
11511050 case 'H4':
11521051 $this->sStartList = '<DIV' . $_listattr . '>';
11531052 $this->sEndList = '</DIV>';
1154 - $this->sStartHeading = '<' . $outputmode .'>';
1155 - $this->sEndHeading = '</' . $outputmode . '>';
 1053+ $this->sStartHeading = '<' . $listmode .'>';
 1054+ $this->sEndHeading = '</' . $listmode . '>';
11561055 break;
11571056 }
11581057 }
11591058 }
 1059+
 1060+
 1061+class DPL2 {
 1062+
 1063+ var $mArticles;
 1064+ var $mHeadingType; // type of heading: category, user, etc. (depends on 'ordermethod' param)
 1065+ var $mHListMode; // html list mode for headings
 1066+ var $mListMode; // html list mode for pages
 1067+ var $mParser;
 1068+ var $mParserOptions;
 1069+ var $mParserTitle;
 1070+ var $mOutput;
 1071+
 1072+ function DPL2($headings, $articles, $headingtype, $hlistmode, $listmode, $parser, $poptions, $ptitle) {
 1073+ $this->mArticles = $articles;
 1074+ $this->mListMode = $listmode;
 1075+ $this->mParser = $parser;
 1076+ $this->mParserOptions = $poptions;
 1077+ $this->mParserTitle = $ptitle;
 1078+
 1079+ if(!empty($headings)) {
 1080+ $this->mHeadingType = $headingtype;
 1081+ $this->mHListMode = $hlistmode;
 1082+ $this->mOutput .= $hlistmode->sStartList;
 1083+ $headingStart = 0;
 1084+ foreach($headings as $heading => $headingCount) {
 1085+ $headingLink = $articles[$headingStart]->mParentHLink;
 1086+ $this->mOutput .= $hlistmode->sStartItem;
 1087+ $this->mOutput .= $hlistmode->sStartHeading . $headingLink . $hlistmode->sEndHeading;
 1088+ $this->mOutput .= $this->formatCount($headingCount);
 1089+ $this->mOutput .= $this->formatList($headingStart, $headingCount);
 1090+ $this->mOutput .= $hlistmode->sEndItem;
 1091+ $headingStart += $headingCount;
 1092+ }
 1093+ $this->mOutput .= $hlistmode->sEndList;
 1094+ } else
 1095+ $this->mOutput .= $this->formatList(0, count($articles));
 1096+ }
 1097+
 1098+ function formatCount($numart) {
 1099+ global $wgLang;
 1100+ if($this->mHeadingType == 'category')
 1101+ $message = 'categoryarticlecount';
 1102+ else
 1103+ $message = 'dpl2_articlecount';
 1104+ return $this->msgExt( $message, array( 'parse' ), $numart);
 1105+ }
 1106+
 1107+ function formatList($iStart, $iCount) {
 1108+ global $wgUser, $wgLang, $wgContLang;
 1109+
 1110+ $mode = $this->mListMode;
 1111+ //categorypage-style list output mode
 1112+ if($mode->name == 'category')
 1113+ return $this->formatCategoryList($iStart, $iCount);
 1114+
 1115+ //other list modes
 1116+ $sk = & $wgUser->getSkin();
 1117+ // generate link to Special:Categories (used if addcategories=true)
 1118+ $tSpecCats = Title::makeTitle( NS_SPECIAL, 'Categories' );
 1119+ $sSpecCatsLnk = $sk->makeKnownLinkObj( $tSpecCats, wfMsg('categories'));
 1120+
 1121+ //process results of query, outputing equivalent of <li>[[Article]]</li> for each result,
 1122+ //or something similar if the list uses other startlist/endlist;
 1123+ $r = $mode->sStartList;
 1124+ for ($i = $iStart; $i < $iStart+$iCount; $i++) {
 1125+ if($i > $iStart)
 1126+ $r .= $mode->sInline; //If mode is not 'inline', sInline attribute is empty, so does nothing
 1127+ $r .= $mode->sStartItem;
 1128+ $article = $this->mArticles[$i];
 1129+ if($article->mDate != '')
 1130+ $r .= $wgLang->timeanddate($article->mDate, true) . ': ';
 1131+ $r .= $article->mLink;
 1132+ if($article->mCounter != '') {
 1133+ // Adapted from SpecialPopularPages::formatResult()
 1134+ $nv = $this->msgExt( 'nviews', array( 'parsemag', 'escape'), $wgLang->formatNum( $article->mCounter ) );
 1135+ $r .= ' ' . $wgContLang->getDirMark() . '(' . $nv . ')';
 1136+ }
 1137+ if($article->mUserLink != '')
 1138+ $r .= ' . . ' . $article->mUserLink;
 1139+ if( !empty($article->mCategoryLinks) )
 1140+ $r .= ' . . <SMALL>' . $sSpecCatsLnk . ': ' . implode(' | ', $article->mCategoryLinks) . '</SMALL>';
 1141+ $r .= $mode->sEndItem;
 1142+ }
 1143+ $r .= $mode->sEndList;
 1144+ return $r;
 1145+ }
 1146+
 1147+ //slightly different from CategoryPage::formatList() (no need to instantiate a CategoryPage object)
 1148+ function formatCategoryList($iStart, $iCount) {
 1149+ global $wgDPL2CategoryStyleListCutoff;
 1150+
 1151+ for($i = $iStart; $i < $iStart + $iCount; $i++) {
 1152+ $aArticles[] = $this->mArticles[$i]->mLink;
 1153+ $aArticles_start_char[] = $this->mArticles[$i]->mStartChar;
 1154+ }
 1155+ require_once ('CategoryPage.php');
 1156+ if ( count ( $aArticles ) > $wgDPL2CategoryStyleListCutoff ) {
 1157+ return CategoryPage::columnList( $aArticles, $aArticles_start_char );
 1158+ } elseif ( count($aArticles) > 0) {
 1159+ // for short lists of articles in categories.
 1160+ return CategoryPage::shortList( $aArticles, $aArticles_start_char );
 1161+ }
 1162+ return '';
 1163+ }
 1164+
 1165+ /**
 1166+ * Returns message in the requested format after parsing wikitext to html
 1167+ * This is meant to be equivalent to wfMsgExt() with parse, parsemag and escape as available options but using the DPL2 local parser instead of the global one (bugfix).
 1168+ */
 1169+ function msgExt( $key, $options ) {
 1170+ $args = func_get_args();
 1171+ array_shift( $args );
 1172+ array_shift( $args );
 1173+
 1174+ if( !is_array($options) ) {
 1175+ $options = array($options);
 1176+ }
 1177+
 1178+ $string = wfMsgGetKey( $key, true, false, false );
 1179+
 1180+ $string = wfMsgReplaceArgs( $string, $args );
 1181+
 1182+ if( in_array('parse', $options) ) {
 1183+ $this->mParserOptions->setInterfaceMessage(true);
 1184+ $parserOutput = $this->mParser->parse( $string, $this->mParserTitle, $this->mParserOptions,
 1185+ true, true );
 1186+ $this->mParserOptions->setInterfaceMessage(false);
 1187+ $string = $parserOutput->getText();
 1188+ } elseif ( in_array('parsemag', $options) ) {
 1189+ $parser = new Parser();
 1190+ $parserOptions = new ParserOptions();
 1191+ $parserOptions->setInterfaceMessage( true );
 1192+ $parser->startExternalParse( $this->mParserTitle, $parserOptions, OT_MSG );
 1193+ $string = $parser->transformMsg( $string, $parserOptions );
 1194+ }
 1195+
 1196+ if ( in_array('escape', $options) ) {
 1197+ $string = htmlspecialchars ( $string );
 1198+ }
 1199+
 1200+ return $string;
 1201+ }
 1202+
 1203+ function getText() {
 1204+ return $this->mOutput;
 1205+ }
 1206+
 1207+}
 1208+
 1209+
 1210+class DPL2Logger {
 1211+ var $iDebugLevel;
 1212+
 1213+ function DPL2Logger() {
 1214+ global $wgDPL2Options;
 1215+ $this->iDebugLevel = $wgDPL2Options['debug']['default'];
 1216+ }
 1217+
 1218+ function msg($msgid) {
 1219+ global $wgDPL2DebugMinLevels;
 1220+ if($this->iDebugLevel >= $wgDPL2DebugMinLevels[$msgid]) {
 1221+ $args = func_get_args();
 1222+ array_shift( $args );
 1223+ /**
 1224+ * @todo add a DPL id to identify the DPL tag that generates the message, in case of multiple DPLs in the page
 1225+ */
 1226+ return '%DPL2-' . DPL2_VERSION . '-' . wfMsg('dpl2_debug_' . $msgid, $args) . '<BR/>';
 1227+ }
 1228+ return '';
 1229+ }
 1230+
 1231+ function msgWrongParam($paramvar, $val) {
 1232+ global $wgContLang, $wgDPL2Options;
 1233+ $msgid = DPL2_WARN_WRONGPARAM;
 1234+ switch($paramvar) {
 1235+ case 'namespace':
 1236+ case 'notnamespace':
 1237+ $msgid = DPL2_ERR_WRONGNS;
 1238+ break;
 1239+ case 'linksto':
 1240+ $msgid = DPL2_ERR_WRONGLINKSTO;
 1241+ break;
 1242+ case 'count':
 1243+ case 'titlemaxlength':
 1244+ $msgid = DPL2_WARN_WRONGPARAM_INT;
 1245+ break;
 1246+ }
 1247+ $paramoptions = array_unique($wgDPL2Options[$paramvar]);
 1248+ sort($paramoptions);
 1249+ return $this->msg( $msgid, $paramvar, $val, $wgDPL2Options[$paramvar]['default'], implode(' | ', $paramoptions ));
 1250+ }
 1251+
 1252+}
11601253 ?>

Status & tagging log