Index: trunk/extensions/intersection/DynamicPageList2.php |
— | — | @@ -1,668 +0,0 @@ |
2 | | -<?php |
3 | | -/* |
4 | | - |
5 | | - Version: |
6 | | - Hack v0.5 (DynamicPageList2 is based on DynamicPageList) |
7 | | - |
8 | | - Purpose:outputs a union of articles residing in a selection |
9 | | - of categories and namespaces using configurable output- and |
10 | | - ordermethods |
11 | | - |
12 | | - Contributors: |
13 | | - n:en:User:IlyaHaykinson n:en:User:Amgine w:de:Benutzer:Unendlich m:User:Dangerman |
14 | | - http://en.wikinews.org/wiki/User:Amgine |
15 | | - http://en.wikinews.org/wiki/User:IlyaHaykinson |
16 | | - http://de.wikipedia.org/wiki/Benutzer:Unendlich |
17 | | - http://meta.wikimedia.org/wiki/User:Dangerman |
18 | | - |
19 | | - Licence: |
20 | | - This program is free software; you can redistribute it and/or modify |
21 | | - it under the terms of the GNU General Public License as published by |
22 | | - the Free Software Foundation; either version 2 of the License, or |
23 | | - (at your option) any later version. |
24 | | - |
25 | | - This program is distributed in the hope that it will be useful, |
26 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
27 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
28 | | - GNU General Public License for more details. |
29 | | - |
30 | | - You should have received a copy of the GNU General Public License along |
31 | | - with this program; if not, write to the Free Software Foundation, Inc., |
32 | | - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
33 | | - http://www.gnu.org/copyleft/gpl.html |
34 | | - |
35 | | - Installation: |
36 | | - Add following to LocalSettings.php: |
37 | | - include("extensions/intersection/DynamicPageList2.php"); |
38 | | -*/ |
39 | | - |
40 | | - |
41 | | -$wgExtensionFunctions[] = "wfDynamicPageList2"; |
42 | | -$wgExtensionCredits['parserhook'][] = array( |
43 | | - 'name' => 'DynamicPageList2', |
44 | | - 'author'=>'[http://en.wikinews.org/wiki/User:IlyaHaykinson IlyaHaykinson], [http://en.wikinews.org/wiki/User:Amgine Amgine], [http://de.wikipedia.org/wiki/Benutzer:Unendlich Unendlich], [http://meta.wikimedia.org/wiki/User:Dangerman Cyril Dangerville]', |
45 | | - 'url'=>'http://meta.wikimedia.org/wiki/DynamicPageList2', |
46 | | - 'description'=>'hack of the original [http://meta.wikimedia.org/wiki/DynamicPageList DynamicPageList] extension from DynamicPageList featuring many Improvements', |
47 | | - 'version'=>'0.5.1' |
48 | | - ); |
49 | | - |
50 | | -$wgDPL2MaxCategoryCount = 4; // Maximum number of categories allowed in the Query |
51 | | -$wgDPL2MinCategoryCount = 0; // Minimum number of categories needed in the Query |
52 | | -$wgDPL2MaxResultCount = 50; // Maximum number of results to allow |
53 | | -$wgDPL2CategoryStyleListCutoff = 6; //Max length to format a list of articles chunked by letter as bullet list, if list bigger, columnar format user (same as cutoff arg for CategoryPage::formatList()) |
54 | | -$wgDPL2AllowUnlimitedCategories = true; // Allow unlimited categories in the Query |
55 | | -$wgDPL2AllowUnlimitedResults = true; // Allow unlimited results to be shown |
56 | | - |
57 | | - |
58 | | -function wfDynamicPageList2() { |
59 | | - global $wgParser, $wgMessageCache; |
60 | | - |
61 | | - $wgMessageCache->addMessages( array( |
62 | | - 'dpl2_toomanycats' => 'DynamicPageList2: Too many categories!', |
63 | | - 'dpl2_toofewcats' => 'DynamicPageList2: Too few categories!', |
64 | | - 'dpl2_noresults' => 'DynamicPageList2: No results!', |
65 | | - 'dpl2_noincludedcatsorns' => 'DynamicPageList2: You need to include/exclude at least one category or include/exclude at least one namespace!', |
66 | | - 'dpl2_noincludedcatsbutcatdate' => "DynamicPageList2: You need to include at least one category if you want to use 'addfirstcategorydate=true' or 'ordermethod=categoryadd'!", |
67 | | - 'dpl2_morethanonecatbutcatdate' => "DynamicPageList2: If you include more than one category you cannot use 'addfirstcategorydate=true' or 'ordermethod=categoryadd'!", |
68 | | - 'dpl2_addmorethanonetypeofdate' => 'DynamicPageList2: You cannot add more than one type of date at a time.', |
69 | | - 'dpl2_catoutputwithwrongordermethod' => "DynamicPageList2: You have to use 'ordermethod=title' or 'ordermethod=category' when using category-style output!", |
70 | | - 'dpl2_addpagetoucheddatewithwrongordermethod' => "DynamicPageList2: You cannot use 'addpagetoucheddate=true' with 'ordermethod=firstedit' or 'ordermethod=lastedit' or 'ordermethod=categoryadd'.", |
71 | | - 'dpl2_addeditdatewithwrongordermethod' => "DynamicPageList2: You have to use 'ordermethod=firstedit' or 'ordermethod=lastedit' when using 'addeditdate=true'.", |
72 | | - 'dpl2_adduserwithwrongordermethod' => "DynamicPageList2: You have to use 'ordermethod=firstedit' or 'ordermethod=lastedit' when using 'adduser=true'." |
73 | | - ) |
74 | | - ); |
75 | | - /* |
76 | | - TODO: allow 'adduser=true' for other order methods. |
77 | | - In fact, a page may be edited by multiple users. Which user(s) should we show? all? the first or the last one? |
78 | | - Suggested solution: use values such as 'all', 'first' or 'last' for the adduser parameter. |
79 | | - */ |
80 | | - $wgParser->setHook( "DPL", "DynamicPageList2" ); |
81 | | -} |
82 | | - |
83 | | - |
84 | | -// The callback function for converting the input text to HTML output |
85 | | -function DynamicPageList2( $input, $params, &$parser ) { |
86 | | - |
87 | | - error_reporting(E_ALL); |
88 | | - |
89 | | - global $wgUser, $wgContLang, $wgDPL2MaxCategoryCount, $wgDPL2MinCategoryCount, $wgDPL2MaxResultCount, $wgDPL2AllowUnlimitedCategories, $wgDPL2AllowUnlimitedResults; |
90 | | - |
91 | | - // INVALIDATE CACHE |
92 | | - $parser->disableCache(); |
93 | | - |
94 | | - $aParams = array(); |
95 | | - |
96 | | - // Default Values |
97 | | - $sOrderMethod = 'title'; |
98 | | - $sOrder = 'descending'; |
99 | | - $sPageOutputMode = 'unordered'; |
100 | | - $sCatOutputMode = 'unordered'; |
101 | | - $sRedirects = 'exclude'; |
102 | | - $sInlSymbol = '-'; |
103 | | - $bShowNamespace = true; |
104 | | - $bSuppressErrors = false; |
105 | | - $bAddFirstCategoryDate = false; |
106 | | - $bAddPageTouchedDate = false; |
107 | | - $bAddEditDate = false; |
108 | | - $bAddUser = false; |
109 | | - $bAddCategories = false; |
110 | | - $bCountSet = false; |
111 | | - $aaIncludeCategories = array(); // $aaIncludeCategories is a two 2-dimensional array: Memberarrays are linked using 'AND' |
112 | | - $aExcludeCategories = array(); |
113 | | - $aNamespaces = array(); |
114 | | - $aExcludeNamespaces = array(); |
115 | | - |
116 | | - //Local parser created. See http://meta.wikimedia.org/wiki/MediaWiki_extensions_FAQ#How_do_I_render_wikitext_in_my_extension.3F |
117 | | - $localParser = new Parser(); |
118 | | - $poptions = $parser->mOptions; |
119 | | - |
120 | | -// ###### PARSE PARAMETERS ###### |
121 | | - $aParams = explode("\n", $input); |
122 | | - |
123 | | - foreach($aParams as $sParam) { |
124 | | - |
125 | | - $aParam = explode("=", $sParam); |
126 | | - if( count( $aParam ) < 2 ) |
127 | | - continue; |
128 | | - $sType = trim($aParam[0]); |
129 | | - $sArg = trim($aParam[1]); |
130 | | - |
131 | | - switch ($sType) { |
132 | | - case 'category': |
133 | | - $aCategories = array(); // Categories in one line separated by '|' are linked using 'OR' |
134 | | - $aParams = explode("|", $sArg); |
135 | | - foreach($aParams as $sParam) { |
136 | | - $sParam=trim($sParam); |
137 | | - $title = Title::newFromText($localParser->transformMsg($sParam, $poptions)); |
138 | | - if( $title != NULL ) |
139 | | - $aCategories[] = $title; |
140 | | - } |
141 | | - if (!empty($aCategories)) |
142 | | - $aaIncludeCategories[] = $aCategories; |
143 | | - break; |
144 | | - |
145 | | - case 'notcategory': |
146 | | - $title = Title::newFromText($localParser->transformMsg($sArg, $poptions)); |
147 | | - if( $title != NULL ) |
148 | | - $aExcludeCategories[] = $title; |
149 | | - break; |
150 | | - |
151 | | - case 'namespace': |
152 | | - $aParams = explode("|", $sArg); |
153 | | - foreach($aParams as $sParam) { |
154 | | - $sParam=trim($sParam); |
155 | | - $sNS = $wgContLang->getNsIndex($sParam); |
156 | | - if ( $sNS != NULL ) |
157 | | - $aNamespaces[] = $sNS; |
158 | | - elseif (intval($sParam) >= 0) |
159 | | - $aNamespaces[] = intval($sParam); |
160 | | - } |
161 | | - break; |
162 | | - |
163 | | - case 'notnamespace': |
164 | | - $sArg=trim($sArg); |
165 | | - $sNS = $wgContLang->getNsIndex($sArg); |
166 | | - if ( $sNS != NULL ) |
167 | | - $aExcludeNamespaces[] = $sNS; |
168 | | - elseif (intval($sArg) >= 0) |
169 | | - $aExcludeNamespaces[] = intval($sArg); |
170 | | - break; |
171 | | - |
172 | | - case 'count': |
173 | | - //ensure that $iCount is a number; |
174 | | - $iCount = IntVal( $sArg ); |
175 | | - $bCountSet = true; |
176 | | - break; |
177 | | - |
178 | | - //mode for list of pages (possibly within a category if 'ordermethod=category', see 'categorymode' parameter) |
179 | | - //TODO: solve the issue: addpagetoucheddate, addeditdate, adduser, addcategories have no effect with 'mode=category' |
180 | | - case 'mode': |
181 | | - if ( in_array($sArg, array('none','ordered','unordered','category','inline')) ) |
182 | | - $sPageOutputMode = $sArg; |
183 | | - break; |
184 | | - |
185 | | - //mode at the category level, used with ordermethod=category only: |
186 | | - //ordered, unordered, definition list, or section, subsection, sub-subsection, etc. |
187 | | - case 'categorymode': |
188 | | - if ( in_array($sArg, array('ordered','unordered','definition')) || preg_match('/^((sub-)*sub)?section$/', $sArg)) |
189 | | - $sCatOutputMode = $sArg; |
190 | | - break; |
191 | | - |
192 | | - case 'inlinesymbol': |
193 | | - $sInlSymbol = strip_tags($sArg); |
194 | | - break; |
195 | | - |
196 | | - case 'order': |
197 | | - if ( in_array($sArg, array('ascending','descending')) ) |
198 | | - $sOrder = $sArg; |
199 | | - break; |
200 | | - |
201 | | - // TODO: add order methods: (category,title), (category,pagetouched), etc. |
202 | | - case 'ordermethod': |
203 | | - if ( in_array($sArg, array('pagetouched','firstedit','lastedit','categoryadd','title','category')) ) |
204 | | - $sOrderMethod = $sArg; |
205 | | - break; |
206 | | - |
207 | | - case 'redirects': |
208 | | - if ( in_array($sArg, array('include','only','exclude')) ) |
209 | | - $sRedirects = $sArg; |
210 | | - break; |
211 | | - |
212 | | - case 'suppresserrors': |
213 | | - if ($sArg == 'true') $bSuppressErrors = true; |
214 | | - if ($sArg == 'false') $bSuppressErrors = false; |
215 | | - break; |
216 | | - |
217 | | - case 'addfirstcategorydate': |
218 | | - if ($sArg == 'true') $bAddFirstCategoryDate = true; |
219 | | - if ($sArg == 'false') $bAddFirstCategoryDate = false; |
220 | | - break; |
221 | | - |
222 | | - case 'addpagetoucheddate': |
223 | | - if ($sArg == 'true') $bAddPageTouchedDate = true; |
224 | | - if ($sArg == 'false') $bAddPageTouchedDate = false; |
225 | | - break; |
226 | | - |
227 | | - case 'addeditdate': //default |
228 | | - if ($sArg == 'true') $bAddEditDate = true; |
229 | | - if ($sArg == 'false') $bAddEditDate = false; |
230 | | - break; |
231 | | - |
232 | | - case 'adduser': |
233 | | - if ($sArg == 'true') $bAddUser = true; |
234 | | - if ($sArg == 'false') $bAddUser = false; |
235 | | - break; |
236 | | - |
237 | | - case 'addcategories': |
238 | | - if ($sArg == 'true') $bAddCategories = true; |
239 | | - if ($sArg == 'false') $bAddCategories = false; |
240 | | - break; |
241 | | - |
242 | | - case 'shownamespace': |
243 | | - if ($sArg == 'true') $bShowNamespace = true; |
244 | | - if ($sArg == 'false') $bShowNamespace = false; |
245 | | - break; |
246 | | - } |
247 | | - } |
248 | | - |
249 | | - $iIncludeCatCount = count($aaIncludeCategories); |
250 | | - $iTotalIncludeCatCount = count($aaIncludeCategories,COUNT_RECURSIVE) - $iIncludeCatCount; |
251 | | - $iExcludeCatCount = count($aExcludeCategories); |
252 | | - $iTotalCatCount = $iIncludeCatCount + $iExcludeCatCount; |
253 | | - |
254 | | -// ###### CHECKS ON PARAMETERS ###### |
255 | | - |
256 | | - // no included/excluded categories or namespaces!! |
257 | | - if ($iTotalCatCount == 0 && empty($aNamespaces) && empty($aExcludeNamespaces)) |
258 | | - return htmlspecialchars( wfMsg( 'dpl2_noincludedcatsorns' ) ); |
259 | | - |
260 | | - // too many categories!! |
261 | | - if ( ($iTotalCatCount > $wgDPL2MaxCategoryCount) && (!$wgDPL2AllowUnlimitedCategories) ) |
262 | | - return htmlspecialchars( wfMsg( 'dpl2_toomanycats' ) ); |
263 | | - |
264 | | - // too few categories!! |
265 | | - if ($iTotalCatCount < $wgDPL2MinCategoryCount) |
266 | | - return htmlspecialchars( wfMsg( 'dpl2_toofewcats' ) ); |
267 | | - |
268 | | - // no included categories but ordermethod=categoryadd or addfirstcategorydate=true!! |
269 | | - if ($iTotalIncludeCatCount == 0 && ($sOrderMethod == 'categoryadd' || $bAddFirstCategoryDate == true) ) |
270 | | - return htmlspecialchars( wfMsg( 'dpl2_noincludedcatsbutcatdate' ) ); |
271 | | - |
272 | | - // more than one included category but ordermethod=categoryadd or addfirstcategorydate=true!! |
273 | | - if ($iTotalIncludeCatCount > 1 && ($sOrderMethod == 'categoryadd' || $bAddFirstCategoryDate == true) ) |
274 | | - return htmlspecialchars( wfMsg( 'dpl2_morethanonecatbutcatdate' ) ); |
275 | | - |
276 | | - // add one type of date at a time!! |
277 | | - // TODO: this may be more elegant using a XOR operator |
278 | | - if( ($bAddPageTouchedDate && ($bAddFirstCategoryDate || $bAddEditDate)) || ($bAddFirstCategoryDate && $bAddEditDate) ) |
279 | | - return htmlspecialchars( wfMsg( 'dpl2_addmorethanonetypeofdate' ) ); |
280 | | - |
281 | | - // category-style output requested but not ordermethod=title!! |
282 | | - if ($sPageOutputMode == 'category' && $sOrderMethod != 'title' && $sOrderMethod != 'category') |
283 | | - return htmlspecialchars( wfMsg( 'dpl2_catoutputwithwrongordermethod' ) ); |
284 | | - |
285 | | - // addpagetoucheddate=true with unappropriate order methods |
286 | | - if( $bAddPageTouchedDate && ($sOrderMethod == 'firstedit' || $sOrderMethod == 'lastedit' || $sOrderMethod == 'categoryadd') ) |
287 | | - return htmlspecialchars( wfMsg( 'dpl2_addpagetoucheddatewithwrongordermethod' ) ); |
288 | | - |
289 | | - // addeditdate=true but not (ordermethod=firstedit or ordermethod=lastedit) |
290 | | - // One of these 2 ordermethods determines the edit date to add. |
291 | | - if( $bAddEditDate && $sOrderMethod != 'firstedit' && $sOrderMethod != 'lastedit') |
292 | | - return htmlspecialchars( wfMsg( 'dpl2_addeditdatewithwrongordermethod' ) ); |
293 | | - |
294 | | - // adduser=true but not (ordermethod=firstedit or ordermethod=lastedit) |
295 | | - /* |
296 | | - TODO: allow to add user for other order methods. |
297 | | - The fact is a page may be edited by multiple users. Which user(s) should we show? all? the first or the last one? |
298 | | - Ideally, we could use values such as 'all', 'first' or 'last' for the adduser parameter. |
299 | | - */ |
300 | | - if( $bAddUser && $sOrderMethod != 'firstedit' && $sOrderMethod != 'lastedit') |
301 | | - return htmlspecialchars( wfMsg( 'dpl2_adduserwithwrongordermethod' ) ); |
302 | | - |
303 | | - // justify limits |
304 | | - if ($bCountSet) { |
305 | | - if ($iCount > $wgDPL2MaxResultCount) |
306 | | - $iCount = $wgDPL2MaxResultCount; |
307 | | - } else |
308 | | - if (!$wgDPL2AllowUnlimitedResults) { |
309 | | - $iCount = $wgDPL2MaxResultCount; |
310 | | - $bCountSet = true; |
311 | | - } |
312 | | - |
313 | | - |
314 | | -// ###### BUILD SQL QUERY ###### |
315 | | - |
316 | | - $dbr =& wfGetDB( DB_SLAVE ); |
317 | | - $sPageTable = $dbr->tableName( 'page' ); |
318 | | - $sSqlPage_touched = ''; |
319 | | - $sCategorylinksTable = $dbr->tableName( 'categorylinks' ); |
320 | | - $sSqlCl_to = ''; |
321 | | - $sSqlCats = ''; |
322 | | - $sSqlCl_timestamp = ''; |
323 | | - $sSqlCl1Table = ''; |
324 | | - $sSqlCond_page_cl1 = ''; |
325 | | - $sSqlCl2Table = ''; |
326 | | - $sSqlCond_page_cl2 = ''; |
327 | | - $sRevisionTable = $dbr->tableName( 'revision' ); |
328 | | - $sSqlRevision = ''; |
329 | | - $sSqlRev_timestamp = ''; |
330 | | - $sSqlRev_user = ''; |
331 | | - $sSqlCond_page_rev = ''; |
332 | | - |
333 | | - switch ($sOrderMethod) { |
334 | | - case 'firstedit': |
335 | | - $sSqlRevision = "$sRevisionTable, "; |
336 | | - $sSqlRev_timestamp = ', min(rev_timestamp) AS rev_timestamp'; |
337 | | - $sSqlCond_page_rev = ' AND page_id=rev_page'; |
338 | | - break; |
339 | | - case 'lastedit': |
340 | | - $sSqlRevision = "$sRevisionTable, "; |
341 | | - $sSqlRev_timestamp = ', max(rev_timestamp) AS rev_timestamp'; |
342 | | - $sSqlCond_page_rev = ' AND page_id=rev_page'; |
343 | | - break; |
344 | | - case 'category': |
345 | | - $sSqlCl_to = 'cl1.cl_to, '; |
346 | | - $sSqlCl1Table = "$sCategorylinksTable AS cl1"; |
347 | | - $sSqlCond_page_cl1 = 'page_id=cl1.cl_from'; |
348 | | - break; |
349 | | - } |
350 | | - |
351 | | - if ($bAddFirstCategoryDate) |
352 | | - //format cl_timestamp field (type timestamp) to string in same format as rev_timestamp field |
353 | | - //to make it compatible with $wgLang->date() function used in function DPL2OutputListStyle() to show "firstcategorydate" |
354 | | - $sSqlCl_timestamp = ", DATE_FORMAT( c1.cl_timestamp, '%Y%m%d%H%i%s' ) AS cl_timestamp"; |
355 | | - if ($bAddPageTouchedDate) |
356 | | - $sSqlPage_touched = ', page_touched'; |
357 | | - if ($bAddUser) |
358 | | - $sSqlRev_user = ', rev_user, rev_user_text'; |
359 | | - if ($bAddCategories) { |
360 | | - $sSqlCats = ", GROUP_CONCAT(DISTINCT cl2.cl_to ORDER BY cl2.cl_to ASC SEPARATOR ' | ') AS cats"; |
361 | | - $sSqlCl2Table = "$sCategorylinksTable AS cl2"; |
362 | | - $sSqlCond_page_cl2 = 'page_id=cl2.cl_from'; |
363 | | - } |
364 | | - |
365 | | - // SELECT ... FROM |
366 | | - $sSqlSelectFrom = "SELECT DISTINCT " . $sSqlCl_to . "page_namespace, page_title" . $sSqlPage_touched . $sSqlRev_timestamp . $sSqlRev_user . $sSqlCats . $sSqlCl_timestamp . " FROM " . $sSqlRevision . $sPageTable; |
367 | | - |
368 | | - // JOIN ... |
369 | | - if($bAddCategories || $sOrderMethod=='category') { |
370 | | - $b2tables = !empty($sSqlCl1Table) && !empty($sSqlCl2Table); |
371 | | - $sSqlSelectFrom .= ' LEFT JOIN (' .$sSqlCl1Table . ($b2tables ? ', ' : '') . $sSqlCl2Table.') ON ('. $sSqlCond_page_cl1 . ($b2tables ? ' AND ' : '') . $sSqlCond_page_cl2 .')'; |
372 | | - } |
373 | | - $iCurrentTableNumber = 0; |
374 | | - for ($i = 0; $i < $iIncludeCatCount; $i++) { |
375 | | - $sSqlSelectFrom .= " INNER JOIN $sCategorylinksTable AS c" . ($iCurrentTableNumber+1); |
376 | | - $sSqlSelectFrom .= ' ON page_id = c' . ($iCurrentTableNumber+1) . '.cl_from'; |
377 | | - $sSqlSelectFrom .= ' AND (c' . ($iCurrentTableNumber+1) . '.cl_to=' . $dbr->addQuotes( $aaIncludeCategories[$i][0]->getDbKey() ); |
378 | | - for ($j = 1; $j < count($aaIncludeCategories[$i]); $j++) |
379 | | - $sSqlSelectFrom .= ' OR c' . ($iCurrentTableNumber+1) . '.cl_to=' . $dbr->addQuotes( $aaIncludeCategories[$i][$j]->getDbKey() ); |
380 | | - $sSqlSelectFrom .= ') '; |
381 | | - $iCurrentTableNumber++; |
382 | | - } |
383 | | - $sSqlWhere = ' WHERE 1=1 '; |
384 | | - for ($i = 0; $i < $iExcludeCatCount; $i++) { |
385 | | - $sSqlSelectFrom .= " LEFT OUTER JOIN $sCategorylinksTable AS c" . ($iCurrentTableNumber+1); |
386 | | - $sSqlSelectFrom .= ' ON page_id = c' . ($iCurrentTableNumber+1) . '.cl_from'; |
387 | | - $sSqlSelectFrom .= ' AND c' . ($iCurrentTableNumber+1) . '.cl_to='. |
388 | | - $dbr->addQuotes( $aExcludeCategories[$i]->getDbKey() ); |
389 | | - $sSqlWhere .= ' AND c' . ($iCurrentTableNumber+1) . '.cl_to IS NULL'; |
390 | | - $iCurrentTableNumber++; |
391 | | - } |
392 | | - |
393 | | - // WHERE ... |
394 | | - // Namespace IS ... |
395 | | - if ( !empty($aNamespaces)) { |
396 | | - $sSqlWhere .= ' AND (page_namespace IN (' . implode (',', $aNamespaces) . '))'; |
397 | | - } |
398 | | - // Namespace IS NOT ... |
399 | | - if ( !empty($aExcludeNamespaces)) { |
400 | | - $sSqlWhere .= ' AND (page_namespace NOT IN (' . implode (',', $aExcludeNamespaces) . '))'; |
401 | | - } |
402 | | - // is_Redirect IS ... |
403 | | - switch ($sRedirects) { |
404 | | - case 'only': |
405 | | - $sSqlWhere .= ' AND page_is_redirect = 1'; |
406 | | - break; |
407 | | - case 'exclude': |
408 | | - $sSqlWhere .= ' AND page_is_redirect = 0'; |
409 | | - break; |
410 | | - } |
411 | | - |
412 | | - $sSqlWhere .= $sSqlCond_page_rev; |
413 | | - |
414 | | - // GROUP BY ... |
415 | | - $sSqlWhere .= ' GROUP BY '. $sSqlCl_to .'page_id';// for min or max(rev_timestamp) (page_id=rev_page) |
416 | | - |
417 | | - // ORDER BY ... |
418 | | - switch ($sOrderMethod) { |
419 | | - case 'pagetouched': |
420 | | - $sSqlWhere .= ' ORDER BY page_touched'; |
421 | | - break; |
422 | | - case 'firstedit': |
423 | | - case 'lastedit': |
424 | | - $sSqlWhere .= ' ORDER BY rev_timestamp'; |
425 | | - break; |
426 | | - case 'categoryadd': |
427 | | - $sSqlWhere .= ' ORDER BY c1.cl_timestamp'; |
428 | | - break; |
429 | | - case 'title': |
430 | | - $sSqlWhere .= ' ORDER BY page_title'; |
431 | | - break; |
432 | | - case 'category': |
433 | | - $sSqlWhere .= ' ORDER BY cl1.cl_to, page_title'; |
434 | | - break; |
435 | | - } |
436 | | - if ($sOrder == 'descending') |
437 | | - $sSqlWhere .= ' DESC'; |
438 | | - else |
439 | | - $sSqlWhere .= ' ASC'; |
440 | | - |
441 | | - // LIMIT .... |
442 | | - if ($bCountSet) |
443 | | - $sSqlWhere .= ' LIMIT ' . $iCount; |
444 | | - |
445 | | - |
446 | | - |
447 | | -// ###### PROCESS SQL QUERY ###### |
448 | | - $output = ''; |
449 | | - //DEBUG: output SQL query |
450 | | - //$output .= 'QUERY: [' . $sSqlSelectFrom . $sSqlWhere . "]<br/>"; |
451 | | - //echo 'QUERY: [' . $sSqlSelectFrom . $sSqlWhere . "]<br />"; |
452 | | - |
453 | | - $res = $dbr->query($sSqlSelectFrom . $sSqlWhere); |
454 | | - if ($dbr->numRows( $res ) == 0) { |
455 | | - if (!$bSuppressErrors) |
456 | | - return htmlspecialchars( wfMsg( 'dpl2_noresults' ) ); |
457 | | - else |
458 | | - return ''; |
459 | | - } |
460 | | - |
461 | | - $sk =& $wgUser->getSkin(); |
462 | | - // generate link to Special:Uncategorizedpages (used if ordermethod=category) |
463 | | - $tSpecUncat = & Title::makeTitle( NS_SPECIAL, 'Uncategorizedpages' ); |
464 | | - $sSpecUncatLnk = $sk->makeKnownLinkObj( $tSpecUncat, wfMsg('uncategorizedpages') ); |
465 | | - // generate title for Special:Contributions (used if adduser=true) |
466 | | - $tSpecContribs =& Title::makeTitle( NS_SPECIAL, 'Contributions' ); |
467 | | - |
468 | | - $aCategories = array(); |
469 | | - $aArticles = array(); |
470 | | - $aArticles_start_char =array(); |
471 | | - $aAddDates = array(); |
472 | | - $aAddUsers = array(); |
473 | | - $aAddCategories = array(); |
474 | | - while( $row = $dbr->fetchObject ( $res ) ) { |
475 | | - //CATEGORY LINKED TO (per page) IF ORDER BY CATEGORY |
476 | | - if($sOrderMethod == 'category') { |
477 | | - if(empty($row->cl_to)) { //uncategorized page |
478 | | - $aCategories[] = $sSpecUncatLnk; |
479 | | - } else { |
480 | | - $tCat = & Title::makeTitle(NS_CATEGORY, $row->cl_to); |
481 | | - $aCategories[] = $sk->makeKnownLinkObj($tCat, $wgContLang->convertHtml($tCat->getText())); |
482 | | - } |
483 | | - } else |
484 | | - $aCategories[] = ''; |
485 | | - |
486 | | - //PAGE LINK |
487 | | - $title = & Title::makeTitle($row->page_namespace, $row->page_title); |
488 | | - if ($bShowNamespace) |
489 | | - $aArticles[] = $sk->makeKnownLinkObj($title); |
490 | | - else |
491 | | - $aArticles[] = $sk->makeKnownLinkObj($title, $wgContLang->convertHtml($title->getText())); |
492 | | - //get first char used for category-style output |
493 | | - $aArticles_start_char[] = $wgContLang->convert($wgContLang->firstChar($row->page_title)); |
494 | | - |
495 | | - //SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE |
496 | | - if($bAddPageTouchedDate) |
497 | | - $aAddDates[] = $row->page_touched; |
498 | | - elseif ($bAddFirstCategoryDate) |
499 | | - $aAddDates[] = $row->cl_timestamp; |
500 | | - elseif ($bAddEditDate) |
501 | | - $aAddDates[] = $row->rev_timestamp; |
502 | | - else |
503 | | - $aAddDates[] = ''; |
504 | | - |
505 | | - //USER/AUTHOR |
506 | | - if($bAddUser) { |
507 | | - if($row->rev_user == 0) { //anonymous user |
508 | | - $aAddUsers[] = $sk->makeKnownLinkObj($tSpecContribs, $row->rev_user_text, 'target=' . $row->rev_user_text); |
509 | | - } else { |
510 | | - $tUser =& Title::makeTitle( NS_USER, $row->rev_user_text ); |
511 | | - /* |
512 | | - The user's page may not exist (->"bad" red link), makeLinkObj() executes a DB query to check that out |
513 | | - TODO: optimize with a LinkBatch on the user titles to get good (user page exists) and bad links, |
514 | | - then use makeKnownLinkObj() for good links (user page exists), makeBrokenLinkObj() on bad ones |
515 | | - */ |
516 | | - $aAddUsers[] = $sk->makeLinkObj($tUser, $wgContLang->convertHtml($tUser->getText())); |
517 | | - } |
518 | | - } else |
519 | | - $aAddUsers[] = ''; |
520 | | - |
521 | | - //CATEGORY LINKS PER PAGE |
522 | | - if(!$bAddCategories || empty($row->cats)) |
523 | | - $aAddCategories[] = ''; |
524 | | - else { |
525 | | - $artCatNames = explode(' | ', $row->cats); |
526 | | - $artCatLinks = array(); |
527 | | - foreach($artCatNames as $artCatName) { |
528 | | - $tArtCat = & Title::makeTitle(NS_CATEGORY, $artCatName); |
529 | | - /* |
530 | | - TODO: see TODO comment for user pages above |
531 | | - */ |
532 | | - $artCatLinks[] = $sk->makeLinkObj($tArtCat, $wgContLang->convertHtml($tArtCat->getText())); |
533 | | - } |
534 | | - $aAddCategories[] = $artCatLinks; |
535 | | - } |
536 | | - } |
537 | | - $dbr->freeResult( $res ); |
538 | | - |
539 | | - |
540 | | -// ###### SHOW OUTPUT ###### |
541 | | - if($sOrderMethod == 'category') { |
542 | | - $catMode = new DPL2OutputMode($sCatOutputMode); |
543 | | - $aCatCounts = array_count_values($aCategories); //count articles per category |
544 | | - $output .= $catMode->sStartList; |
545 | | - $catStart = 0; |
546 | | - foreach($aCatCounts as $cat => $catCount) { |
547 | | - $output .= $catMode->sStartItem; |
548 | | - $output .= $catMode->sStartHeading . $cat . $catMode->sEndHeading; |
549 | | - $output .= '<p>' . DPL2FormatCount($catCount, 'categoryarticlecount') . '</p>'; |
550 | | - if ($sPageOutputMode == 'category') |
551 | | - $output .= DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, $catStart, $catCount); |
552 | | - else |
553 | | - $output .= DPL2OutputListStyle($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $sPageOutputMode, $sInlSymbol, $catStart, $catCount); |
554 | | - $output .= $catMode->sEndItem; |
555 | | - $catStart += $catCount; |
556 | | - } |
557 | | - $output .= $catMode->sEndList; |
558 | | - } elseif($sPageOutputMode == 'category') |
559 | | - $output .= DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, 0, count($aArticles)); |
560 | | - else |
561 | | - $output .= DPL2OutputListStyle($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $sPageOutputMode, $sInlSymbol, 0, count($aArticles)); |
562 | | - |
563 | | - return $output; |
564 | | -} |
565 | | - |
566 | | - |
567 | | -function DPL2OutputListStyle ($aArticles, $aAddDates, $aAddUsers, $aAddCategories, $sOutputMode, $sInlSymbol, $iStart, $iCount) { |
568 | | - global $wgUser, $wgLang; |
569 | | - |
570 | | - $sk = & $wgUser->getSkin(); |
571 | | - // generate link to Special:Categories (used if addcategories=true) |
572 | | - $tSpecCats = & Title::makeTitle( NS_SPECIAL, 'Categories' ); |
573 | | - $sSpecCatsLnk = $sk->makeKnownLinkObj( $tSpecCats, wfMsg('categories')); |
574 | | - |
575 | | - $mode = new DPL2OutputMode($sOutputMode, $sInlSymbol); |
576 | | - //process results of query, outputing equivalent of <li>[[Article]]</li> for each result, |
577 | | - //or something similar if the list uses other startlist/endlist; |
578 | | - $r = $mode->sStartList; |
579 | | - for ($i = $iStart; $i < $iStart+$iCount; $i++) { |
580 | | - $r .= $mode->sStartItem; |
581 | | - if(!empty($aAddDates[$i])) |
582 | | - $r .= $wgLang->date($aAddDates[$i]) . ': '; |
583 | | - $r .= $aArticles[$i]; |
584 | | - if(!empty($aAddUsers[$i])) |
585 | | - $r .= ' . . ' . $aAddUsers[$i]; |
586 | | - if(!empty($aAddCategories[$i])) |
587 | | - $r .= ' . . <small>' . $sSpecCatsLnk . ': ' . implode(' | ', $aAddCategories[$i]) . '</small>'; |
588 | | - if( (($mode->name != 'inline') && ($mode->name != 'none')) || ($i < $iCount-1)) //no inline symbol (inline mode) at end of list |
589 | | - $r .= $mode->sEndItem; |
590 | | - } |
591 | | - $r .= $mode->sEndList; |
592 | | - return $r; |
593 | | -} |
594 | | - |
595 | | -//slightly different from CategoryPage::formatList() (no need to instantiate a CategoryPage object) |
596 | | -function DPL2OutputCategoryStyle($aArticles, $aArticles_start_char, $iStart, $iCount) { |
597 | | - global $wgDPL2CategoryStyleListCutoff; |
598 | | - |
599 | | - $subaArticles = array_slice($aArticles, $iStart, $iCount); |
600 | | - $subaArticles_start_char = array_slice($aArticles_start_char, $iStart, $iCount); |
601 | | - require_once ('CategoryPage.php'); |
602 | | - if ( count ( $subaArticles ) > $wgDPL2CategoryStyleListCutoff ) { |
603 | | - return CategoryPage::columnList( $subaArticles, $subaArticles_start_char ); |
604 | | - } elseif ( count($subaArticles) > 0) { |
605 | | - // for short lists of articles in categories. |
606 | | - return CategoryPage::shortList( $subaArticles, $subaArticles_start_char ); |
607 | | - } |
608 | | - return ''; |
609 | | -} |
610 | | - |
611 | | - |
612 | | -//slightly different from CategoryPage::formatCount() (first argument is the number not an array) |
613 | | -function DPL2FormatCount( $numart, $message ) { |
614 | | - global $wgContLang; |
615 | | - if( $numart == 1 ) { |
616 | | - # Slightly different message to avoid silly plural |
617 | | - $message .= '1'; |
618 | | - } |
619 | | - return wfMsg( $message, $wgContLang->formatNum( $numart ) ); |
620 | | -} |
621 | | - |
622 | | - |
623 | | -class DPL2OutputMode { |
624 | | - var $name; |
625 | | - var $sStartList = ''; |
626 | | - var $sEndList = ''; |
627 | | - var $sStartHeading = ''; |
628 | | - var $sEndHeading = ''; |
629 | | - var $sStartItem = ''; |
630 | | - var $sEndItem = ''; |
631 | | - |
632 | | - function DPL2OutputMode($outputmode, $inlinesymbol = '-') { |
633 | | - $this->name = $outputmode; |
634 | | - switch ($outputmode) { |
635 | | - case 'none': |
636 | | - $this->sEndItem = '<br/>'; |
637 | | - break; |
638 | | - case 'inline': |
639 | | - $this->sEndItem = ' ' . $inlinesymbol . ' '; |
640 | | - break; |
641 | | - case 'ordered': |
642 | | - $this->sStartList = '<ol>'; |
643 | | - $this->sEndList = '</ol>'; |
644 | | - $this->sStartItem = '<li>'; |
645 | | - $this->sEndItem = '</li>'; |
646 | | - break; |
647 | | - case 'unordered': |
648 | | - $this->sStartList = '<ul>'; |
649 | | - $this->sEndList = '</ul>'; |
650 | | - $this->sStartItem = '<li>'; |
651 | | - $this->sEndItem = '</li>'; |
652 | | - break; |
653 | | - case 'definition': |
654 | | - $this->sStartList = '<dl>'; |
655 | | - $this->sEndList = '</dl>'; |
656 | | - $this->sStartHeading = '<dt>'; |
657 | | - $this->sEndHeading = '</dt><dd>'; |
658 | | - $this->sEndItem = '</dd>'; |
659 | | - break; |
660 | | - default: |
661 | | - if(preg_match('/^((sub-)*sub)?section$/', $outputmode)) { |
662 | | - $level = 2 + preg_match_all('/sub/', $outputmode, $matches); |
663 | | - $this->sStartHeading = '<h' . $level . '>'; |
664 | | - $this->sEndHeading = '</h' . $level . '>'; |
665 | | - } |
666 | | - } |
667 | | - } |
668 | | -} |
669 | | -?> |