Correct the address of the FSF in some of the GPL headers
[lhc/web/wiklou.git] / includes / specials / SpecialRandompage.php
1 <?php
2 /**
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 */
19
20 /**
21 * Special page to direct the user to a random page
22 *
23 * @ingroup SpecialPage
24 * @author Rob Church <robchur@gmail.com>, Ilmari Karonen
25 * @license GNU General Public Licence 2.0 or later
26 */
27 class RandomPage extends SpecialPage {
28 private $namespaces; // namespaces to select pages from
29 protected $isRedir = false; // should the result be a redirect?
30 protected $extra = array(); // Extra SQL statements
31
32 public function __construct( $name = 'Randompage' ){
33 global $wgContentNamespaces;
34 $this->namespaces = $wgContentNamespaces;
35 parent::__construct( $name );
36 }
37
38 public function getNamespaces() {
39 return $this->namespaces;
40 }
41
42 public function setNamespace ( $ns ) {
43 if( !$ns || $ns < NS_MAIN ) $ns = NS_MAIN;
44 $this->namespaces = array( $ns );
45 }
46
47 // select redirects instead of normal pages?
48 public function isRedirect(){
49 return $this->isRedir;
50 }
51
52 public function execute( $par ) {
53 global $wgOut, $wgContLang, $wgRequest;
54
55 if ($par) {
56 $this->setNamespace( $wgContLang->getNsIndex( $par ) );
57 }
58
59 $title = $this->getRandomTitle();
60
61 if( is_null( $title ) ) {
62 $this->setHeaders();
63 $wgOut->addWikiMsg( strtolower( $this->mName ) . '-nopages',
64 $this->getNsList(), count( $this->namespaces ) );
65 return;
66 }
67
68 $redirectParam = $this->isRedirect() ? array( 'redirect' => 'no' ) : array();
69 $query = array_merge( $wgRequest->getValues(), $redirectParam );
70 unset( $query['title'] );
71 $wgOut->redirect( $title->getFullUrl( $query ) );
72 }
73
74 /**
75 * Get a comma-delimited list of namespaces we don't have
76 * any pages in
77 * @return String
78 */
79 private function getNsList() {
80 global $wgContLang;
81 $nsNames = array();
82 foreach( $this->namespaces as $n ) {
83 if( $n === NS_MAIN )
84 $nsNames[] = wfMsgForContent( 'blanknamespace' );
85 else
86 $nsNames[] = $wgContLang->getNsText( $n );
87 }
88 return $wgContLang->commaList( $nsNames );
89 }
90
91
92 /**
93 * Choose a random title.
94 * @return Title object (or null if nothing to choose from)
95 */
96 public function getRandomTitle() {
97 $randstr = wfRandom();
98 $title = null;
99 if ( !wfRunHooks( 'SpecialRandomGetRandomTitle', array( &$randstr, &$this->isRedir, &$this->namespaces, &$this->extra, &$title ) ) ) {
100 return $title;
101 }
102 $row = $this->selectRandomPageFromDB( $randstr );
103
104 /* If we picked a value that was higher than any in
105 * the DB, wrap around and select the page with the
106 * lowest value instead! One might think this would
107 * skew the distribution, but in fact it won't cause
108 * any more bias than what the page_random scheme
109 * causes anyway. Trust me, I'm a mathematician. :)
110 */
111 if( !$row )
112 $row = $this->selectRandomPageFromDB( "0" );
113
114 if( $row )
115 return Title::makeTitleSafe( $row->page_namespace, $row->page_title );
116 else
117 return null;
118 }
119
120 private function selectRandomPageFromDB( $randstr ) {
121 global $wgExtraRandompageSQL;
122 $dbr = wfGetDB( DB_SLAVE );
123
124 $use_index = $dbr->useIndexClause( 'page_random' );
125 $page = $dbr->tableName( 'page' );
126
127 $ns = implode( ",", $this->namespaces );
128 $redirect = $this->isRedirect() ? 1 : 0;
129
130 if ( $wgExtraRandompageSQL ) {
131 $this->extra[] = $wgExtraRandompageSQL;
132 }
133 if ( $this->addExtraSQL() ) {
134 $this->extra[] = $this->addExtraSQL();
135 }
136 $extra = '';
137 if ( $this->extra ) {
138 $extra = 'AND (' . implode( ') AND (', $this->extra ) . ')';
139 }
140 $sql = "SELECT page_title, page_namespace
141 FROM $page $use_index
142 WHERE page_namespace IN ( $ns )
143 AND page_is_redirect = $redirect
144 AND page_random >= $randstr
145 $extra
146 ORDER BY page_random";
147
148 $sql = $dbr->limitResult( $sql, 1, 0 );
149 $res = $dbr->query( $sql, __METHOD__ );
150 return $dbr->fetchObject( $res );
151 }
152
153 /* an alternative to $wgExtraRandompageSQL so subclasses
154 * can add their own SQL by overriding this function
155 * @deprecated, append to $this->extra instead
156 */
157 public function addExtraSQL() {
158 return '';
159 }
160 }