r16529 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r16528‎ | r16529 | r16530 >
Date:14:52, 17 September 2006
Author:cdangerville
Status:old
Tags:
Comment:
Release 0.7.0
* Added feature: can perform logical ops on the Uncategorized pages like a "normal" category with 'category' param (uses special value: empty string)
* Added DPL2_ERROR_NOCLVIEW debug msg, in case dpl_clview doesn't exist, necessary for feature above
* Improved comments on (not)category and (not)namespace params
* Improved labelling of categorylinks table aliases in sql
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.6.4
 23+ * @version 0.7.0
2424 */
2525
2626 /*
2727 * Current version
2828 */
29 -define('DPL2_VERSION', '0.6.4');
 29+define('DPL2_VERSION', '0.7.0');
3030
3131 /**
3232 * Register the extension with MediaWiki
@@ -61,6 +61,11 @@
6262 'addpagetoucheddate' => array('default' => 'false', 'false', 'true'),
6363 'adduser' => array('default' => 'false', 'false', 'true'),
6464 /**
 65+ * category= Cat11 | Cat12 | ...
 66+ * category = Cat21 | Cat22 | ...
 67+ * ...
 68+ * [Special value] catX='' (empty string without quotes) means pseudo-categoy of Uncategorized pages
 69+ * Means pages have to be in category (Cat11 OR (inclusive) Cat2 OR...) AND (Cat21 OR Cat22 OR...) AND...
6570 * @todo define 'category' options (retrieve list of categories from 'categorylinks' table?)
6671 */
6772 'category' => NULL,
@@ -120,11 +125,27 @@
121126 * 'none' mode is implemented as a specific submode of 'inline' with <BR/> as inline text
122127 */
123128 'mode' => array('default' => 'unordered', 'category', 'inline', 'none', 'ordered', 'unordered'),
 129+ /**
 130+ * namespace= Ns1 | Ns2 | ...
 131+ * [Special value] NsX='' (empty string without quotes) means Main namespace
 132+ * Means pages have to be in namespace Ns1 OR Ns2 OR...
 133+ */
124134 'namespace' => NULL,
125135 /**
 136+ * notcategory= Cat1
 137+ * notcategory = Cat2
 138+ * ...
 139+ * Means pages can be NEITHER in category Cat1 NOR in Cat2 NOR...
126140 * @todo define 'notcategory' options (retrieve list of categories from 'categorylinks' table?)
127141 */
128142 'notcategory' => NULL,
 143+ /**
 144+ * notnamespace= Ns1
 145+ * notnamespace= Ns2
 146+ * ...
 147+ * [Special value] NsX='' (empty string without quotes) means Main namespace
 148+ * Means pages have to be NEITHER in namespace Ns1 NOR Ns2 NOR...
 149+ */
129150 'notnamespace' => NULL,
130151 'order' => array('default' => 'ascending', 'ascending', 'descending'),
131152 /**
@@ -166,6 +187,7 @@
167188 'DPL2_ERR_CATDATEBUTMORETHAN1CAT' => 1,
168189 'DPL2_ERR_MORETHAN1TYPEOFDATE' => 1,
169190 'DPL2_ERR_WRONGORDERMETHOD' => 1,
 191+ 'DPL2_ERR_NOCLVIEW' => 1,
170192 // WARNINGS
171193 'DPL2_WARN_UNKNOWNPARAM' => 2,
172194 'DPL2_WARN_WRONGPARAM' => 2,
@@ -203,7 +225,7 @@
204226
205227 error_reporting(E_ALL);
206228
207 - global $wgDPL2Options, $wgUser, $wgContLang, $wgDPL2MaxCategoryCount, $wgDPL2MinCategoryCount, $wgDPL2MaxResultCount, $wgDPL2AllowUnlimitedCategories, $wgDPL2AllowUnlimitedResults;
 229+ global $wgUser, $wgContLang, $wgDPL2Options, $wgDPL2MaxCategoryCount, $wgDPL2MinCategoryCount, $wgDPL2MaxResultCount, $wgDPL2AllowUnlimitedCategories, $wgDPL2AllowUnlimitedResults;
208230
209231 // INVALIDATE CACHE
210232 $parser->disableCache();
@@ -255,7 +277,7 @@
256278
257279 foreach($aParams as $iParam => $sParam) {
258280
259 - $aParam = explode("=", $sParam, 2);
 281+ $aParam = explode('=', $sParam, 2);
260282 if( count( $aParam ) < 2 )
261283 continue;
262284 $sType = trim($aParam[0]);
@@ -263,26 +285,31 @@
264286
265287 switch ($sType) {
266288 case 'category':
267 - $aCategories = array(); // Categories in one line separated by '|' are linked using 'OR'
268 - $aParams = explode("|", $sArg);
 289+ // Init array of categories to include
 290+ $aCategories = array();
 291+ $aParams = explode('|', $sArg);
269292 foreach($aParams as $sParam) {
270293 $sParam=trim($sParam);
271 - $title = Title::newFromText($localParser->transformMsg($sParam, $pOptions));
272 - if( $title != NULL )
273 - $aCategories[] = $title;
 294+ if($sParam == '') // include uncategorized pages (special value: empty string)
 295+ $aCategories[] = '';
 296+ else {
 297+ $title = Title::newFromText($localParser->transformMsg($sParam, $pOptions));
 298+ if( $title != NULL )
 299+ $aCategories[] = $title->getDbKey();
 300+ }
274301 }
275302 if( !empty($aCategories) )
276 - $aIncludeCategories[] = $aCategories;
 303+ $aIncludeCategories[] = $aCategories;
277304 break;
278305
279306 case 'notcategory':
280307 $title = Title::newFromText($localParser->transformMsg($sArg, $pOptions));
281308 if( $title != NULL )
282 - $aExcludeCategories[] = $title;
 309+ $aExcludeCategories[] = $title->getDbKey();
283310 break;
284311
285312 case 'namespace':
286 - $aParams = explode("|", $sArg);
 313+ $aParams = explode('|', $sArg);
287314 foreach($aParams as $sParam) {
288315 $sParam=trim($sParam);
289316 // Reject pseudo-namespaces (negative indices): Media (-2) and Special (-1).
@@ -531,10 +558,10 @@
532559 $sSqlCl_to = '';
533560 $sSqlCats = '';
534561 $sSqlCl_timestamp = '';
535 - $sSqlCl1Table = '';
536 - $sSqlCond_page_cl1 = '';
537 - $sSqlCl2Table = '';
538 - $sSqlCond_page_cl2 = '';
 562+ $sSqlClHeadTable = '';
 563+ $sSqlCond_page_cl_head = '';
 564+ $sSqlClTableForGC = '';
 565+ $sSqlCond_page_cl_gc = '';
539566 $sRevisionTable = $dbr->tableName( 'revision' );
540567 $sSqlRevision = '';
541568 $sSqlRev_timestamp = '';
@@ -544,22 +571,22 @@
545572 foreach($aOrderMethods as $sOrderMethod) {
546573 switch ($sOrderMethod) {
547574 case 'category':
548 - $sSqlCl_to = 'cl1.cl_to, ';
549 - $sSqlCl1Table = $sCategorylinksTable . ' AS cl1';
550 - $sSqlCond_page_cl1 = 'page_id=cl1.cl_from';
 575+ $sSqlCl_to = 'cl_head.cl_to, '; // Gives category headings in the result
 576+ $sSqlClHeadTable = $sCategorylinksTable . ' AS cl_head';
 577+ $sSqlCond_page_cl_head = 'page_id=cl_head.cl_from';
551578 break;
552579 case 'firstedit':
553 - $sSqlRevision = $sRevisionTable. ', ';
 580+ $sSqlRevision = $sRevisionTable . ', ';
554581 $sSqlRev_timestamp = ', min(rev_timestamp) AS rev_timestamp';
555582 $sSqlCond_page_rev = ' AND page_id=rev_page';
556583 break;
557584 case 'lastedit':
558 - $sSqlRevision = $sRevisionTable. ', ';
 585+ $sSqlRevision = $sRevisionTable . ', ';
559586 $sSqlRev_timestamp = ', max(rev_timestamp) AS rev_timestamp';
560587 $sSqlCond_page_rev = ' AND page_id=rev_page';
561588 break;
562589 case 'user':
563 - $sSqlRevision = $sRevisionTable. ', ';
 590+ $sSqlRevision = $sRevisionTable . ', ';
564591 break;
565592 }
566593 }
@@ -567,64 +594,90 @@
568595 if ($bAddFirstCategoryDate)
569596 //format cl_timestamp field (type timestamp) to string in same format as rev_timestamp field
570597 //to make it compatible with $wgLang->date() function used in function DPL2OutputListStyle() to show "firstcategorydate"
571 - $sSqlCl_timestamp = ", DATE_FORMAT( c1.cl_timestamp, '%Y%m%d%H%i%s' ) AS cl_timestamp";
 598+ $sSqlCl_timestamp = ", DATE_FORMAT(c1.cl_timestamp, '%Y%m%d%H%i%s') AS cl_timestamp";
572599 if ($bAddPageTouchedDate)
573600 $sSqlPage_touched = ', page_touched';
574601 if ($bAddUser)
575602 $sSqlRev_user = ', rev_user, rev_user_text';
576603 if ($bAddCategories) {
577 - $sSqlCats = ", GROUP_CONCAT(DISTINCT cl2.cl_to ORDER BY cl2.cl_to ASC SEPARATOR ' | ') AS cats";
578 - $sSqlCl2Table = "$sCategorylinksTable AS cl2";
579 - $sSqlCond_page_cl2 = 'page_id=cl2.cl_from';
 604+ $sSqlCats = ", GROUP_CONCAT(DISTINCT cl_gc.cl_to ORDER BY cl_gc.cl_to ASC SEPARATOR ' | ') AS cats"; // Gives list of all categories linked from each article, if any.
 605+ $sSqlClTableForGC = $sCategorylinksTable . ' AS cl_gc'; // Categorylinks table used by the Group Concat (GC) function above
 606+ $sSqlCond_page_cl_gc = 'page_id=cl_gc.cl_from';
580607 }
581608
582609 // SELECT ... FROM
583 - $sSqlSelectFrom = "SELECT DISTINCT " . $sSqlCl_to . "page_namespace, page_title" . $sSqlPage_touched . $sSqlRev_timestamp . $sSqlRev_user . $sSqlCats . $sSqlCl_timestamp . " FROM " . $sSqlRevision . $sPageTable;
 610+ $sSqlSelectFrom = 'SELECT DISTINCT ' . $sSqlCl_to . 'page_namespace, page_title' . $sSqlPage_touched . $sSqlRev_timestamp . $sSqlRev_user . $sSqlCats . $sSqlCl_timestamp . ' FROM ' . $sSqlRevision . $sPageTable;
584611
585 - // JOIN ...
586 - if($bAddCategories || $aOrderMethods[0] == 'category') {
587 - $b2tables = ($sSqlCl1Table != '') && ($sSqlCl2Table != '');
588 - $sSqlSelectFrom .= ' LEFT JOIN (' .$sSqlCl1Table . ($b2tables ? ', ' : '') . $sSqlCl2Table.') ON ('. $sSqlCond_page_cl1 . ($b2tables ? ' AND ' : '') . $sSqlCond_page_cl2 .')';
 612+ // JOIN ...
 613+ if($sSqlClHeadTable != '' || $sSqlClTableForGC != '') {
 614+ $b2tables = ($sSqlClHeadTable != '') && ($sSqlClTableForGC != '');
 615+ $sSqlSelectFrom .= ' LEFT OUTER JOIN (' . $sSqlClHeadTable . ($b2tables ? ', ' : '') . $sSqlClTableForGC . ') ON (' . $sSqlCond_page_cl_head . ($b2tables ? ' AND ' : '') . $sSqlCond_page_cl_gc . ')';
589616 }
590 - $iCurrentTableNumber = 0;
 617+
 618+ // Include categories...
 619+ // If we include the Uncategorized, we use the 'dpl_clview': VIEW of the categorylinks table where we have cl_to='' (empty string) for all uncategorized pages. This VIEW must have been created by the administrator of the mediawiki DB at installation. See the documentation.
 620+ $sDplClView = $dbr->tableName( 'dpl_clview' );
 621+ // If the view is not there, we can't perform logical operations on the Uncategorized.
 622+ $dpl_clview_exists = false;
 623+ $res = $dbr->query( "SHOW TABLE STATUS LIKE '" . trim($sDplClView, '`') . "'" );
 624+ if ($dbr->numRows( $res ) != 0) {
 625+ $dbr->freeResult($res);
 626+ $dpl_clview_exists = true;
 627+ }
 628+
 629+ $iClTable = 0;
591630 for ($i = 0; $i < $iIncludeCatCount; $i++) {
592 - $sSqlSelectFrom .= " INNER JOIN $sCategorylinksTable AS c" . ($iCurrentTableNumber+1);
593 - $sSqlSelectFrom .= ' ON page_id = c' . ($iCurrentTableNumber+1) . '.cl_from';
594 - $sSqlSelectFrom .= ' AND (c' . ($iCurrentTableNumber+1) . '.cl_to=' . $dbr->addQuotes( $aIncludeCategories[$i][0]->getDbKey() );
 631+ $sSqlSelectFrom .= ' INNER JOIN ';
 632+ // If we want the Uncategorized...
 633+ if( in_array('', $aIncludeCategories[$i]) )
 634+ if($dpl_clview_exists)
 635+ $sSqlSelectFrom .= $sDplClView;
 636+ else {
 637+ $sSqlCreate_dpl_clview = 'CREATE VIEW ' . $sDplClView . " AS SELECT COALESCE(cl_from, page_id) AS cl_from, COALESCE(cl_to, '') AS cl_to FROM " . $sPageTable . ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' ON page_id=cl_from';
 638+ $output .= $logger->msg(DPL2_ERR_NOCLVIEW, $sDplClView, $sSqlCreate_dpl_clview);
 639+ return $output;
 640+ }
 641+ else
 642+ $sSqlSelectFrom .= $sCategorylinksTable;
 643+ $sSqlSelectFrom .= ' AS cl' . $iClTable .
 644+ ' ON page_id=cl' . $iClTable . '.cl_from' .
 645+ ' AND (cl' . $iClTable . '.cl_to=' . $dbr->addQuotes($aIncludeCategories[$i][0]);
595646 for ($j = 1; $j < count($aIncludeCategories[$i]); $j++)
596 - $sSqlSelectFrom .= ' OR c' . ($iCurrentTableNumber+1) . '.cl_to=' . $dbr->addQuotes( $aIncludeCategories[$i][$j]->getDbKey() );
 647+ $sSqlSelectFrom .= ' OR cl' . $iClTable . '.cl_to=' . $dbr->addQuotes($aIncludeCategories[$i][$j]);
597648 $sSqlSelectFrom .= ') ';
598 - $iCurrentTableNumber++;
 649+ $iClTable++;
599650 }
 651+
 652+ // Exclude categories... and start the WHERE clause on category fields for exclusion of categories
600653 $sSqlWhere = ' WHERE 1=1 ';
601654 for ($i = 0; $i < $iExcludeCatCount; $i++) {
602 - $sSqlSelectFrom .= " LEFT OUTER JOIN $sCategorylinksTable AS c" . ($iCurrentTableNumber+1);
603 - $sSqlSelectFrom .= ' ON page_id = c' . ($iCurrentTableNumber+1) . '.cl_from';
604 - $sSqlSelectFrom .= ' AND c' . ($iCurrentTableNumber+1) . '.cl_to='.
605 - $dbr->addQuotes( $aExcludeCategories[$i]->getDbKey() );
606 - $sSqlWhere .= ' AND c' . ($iCurrentTableNumber+1) . '.cl_to IS NULL';
607 - $iCurrentTableNumber++;
 655+ $sSqlSelectFrom .=
 656+ ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' AS cl' . $iClTable .
 657+ ' ON page_id=cl' . $iClTable . '.cl_from' .
 658+ ' AND cl' . $iClTable . '.cl_to=' . $dbr->addQuotes($aExcludeCategories[$i]);
 659+ $sSqlWhere .= ' AND cl' . $iClTable . '.cl_to IS NULL';
 660+ $iClTable++;
608661 }
609662
610 - // WHERE ...
 663+ // WHERE... (actually finish the WHERE clause we may have started if we excluded categories - see above)
611664 // Namespace IS ...
612665 if ( !empty($aNamespaces)) {
613 - $sSqlWhere .= ' AND (page_namespace IN (' . implode (',', $aNamespaces) . '))';
 666+ $sSqlWhere .= ' AND page_namespace IN (' . implode (', ', $aNamespaces) . ')';
614667 }
615668 // Namespace IS NOT ...
616669 if ( !empty($aExcludeNamespaces)) {
617 - $sSqlWhere .= ' AND (page_namespace NOT IN (' . implode (',', $aExcludeNamespaces) . '))';
 670+ $sSqlWhere .= ' AND page_namespace NOT IN (' . implode (', ', $aExcludeNamespaces) . ')';
618671 }
619672 // rev_minor_edit IS
620673 if( isset($sMinorEdits) && $sMinorEdits == 'exclude' )
621 - $sSqlWhere .= ' AND rev_minor_edit = 0';
 674+ $sSqlWhere .= ' AND rev_minor_edit=0';
622675 // page_is_redirect IS ...
623676 switch ($sRedirects) {
624677 case 'only':
625 - $sSqlWhere .= ' AND page_is_redirect = 1';
 678+ $sSqlWhere .= ' AND page_is_redirect=1';
626679 break;
627680 case 'exclude':
628 - $sSqlWhere .= ' AND page_is_redirect = 0';
 681+ $sSqlWhere .= ' AND page_is_redirect=0';
629682 break;
630683 }
631684
@@ -641,10 +694,10 @@
642695 $sSqlWhere .= ', ';
643696 switch ($sOrderMethod) {
644697 case 'category':
645 - $sSqlWhere .= 'cl1.cl_to';
 698+ $sSqlWhere .= 'cl_head.cl_to';
646699 break;
647700 case 'categoryadd':
648 - $sSqlWhere .= 'c1.cl_timestamp';
 701+ $sSqlWhere .= 'cl0.cl_timestamp';
649702 break;
650703 case 'firstedit':
651704 case 'lastedit':

Status & tagging log