MediaWiki REL1_37
SpecialRandomPage.php
Go to the documentation of this file.
1<?php
27
34 private $namespaces; // namespaces to select pages from
35 protected $isRedir = false; // should the result be a redirect?
36 protected $extra = []; // Extra SQL statements
37
40
45 public function __construct(
46 $loadBalancer = null,
47 NamespaceInfo $nsInfo = null
48 ) {
49 parent::__construct( is_string( $loadBalancer ) ? $loadBalancer : 'Randompage' );
50 // This class is extended and therefor fallback to global state - T265308
51 $services = MediaWikiServices::getInstance();
52 $this->loadBalancer = $loadBalancer instanceof ILoadBalancer
54 : $services->getDBLoadBalancer();
55 $nsInfo = $nsInfo ?? $services->getNamespaceInfo();
56 $this->namespaces = $nsInfo->getContentNamespaces();
57 }
58
59 public function getNamespaces() {
60 return $this->namespaces;
61 }
62
63 public function setNamespace( $ns ) {
64 if ( !$ns || $ns < NS_MAIN ) {
65 $ns = NS_MAIN;
66 }
67 $this->namespaces = [ $ns ];
68 }
69
70 // select redirects instead of normal pages?
71 public function isRedirect() {
72 return $this->isRedir;
73 }
74
75 public function execute( $par ) {
76 if ( is_string( $par ) ) {
77 // Testing for stringiness since we want to catch
78 // the empty string to mean main namespace only.
79 $this->setNamespace( $this->getContentLanguage()->getNsIndex( $par ) );
80 }
81
82 $title = $this->getRandomTitle();
83
84 if ( $title === null ) {
85 $this->setHeaders();
86 // Message: randompage-nopages, randomredirect-nopages
87 $this->getOutput()->addWikiMsg( strtolower( $this->getName() ) . '-nopages',
88 $this->getNsList(), count( $this->namespaces ) );
89
90 return;
91 }
92
93 $redirectParam = $this->isRedirect() ? [ 'redirect' => 'no' ] : [];
94 $query = array_merge( $this->getRequest()->getValues(), $redirectParam );
95 unset( $query['title'] );
96 $this->getOutput()->redirect( $title->getFullURL( $query ) );
97 }
98
104 private function getNsList() {
105 $contLang = $this->getContentLanguage();
106 $nsNames = [];
107 foreach ( $this->namespaces as $n ) {
108 if ( $n === NS_MAIN ) {
109 $nsNames[] = $this->msg( 'blanknamespace' )->plain();
110 } else {
111 $nsNames[] = $contLang->getNsText( $n );
112 }
113 }
114
115 return $contLang->commaList( $nsNames );
116 }
117
122 public function getRandomTitle() {
123 $randstr = wfRandom();
124 $title = null;
125
126 if ( !$this->getHookRunner()->onSpecialRandomGetRandomTitle(
127 $randstr, $this->isRedir, $this->namespaces,
128 $this->extra, $title )
129 ) {
130 return $title;
131 }
132
133 $row = $this->selectRandomPageFromDB( $randstr, __METHOD__ );
134
135 /* If we picked a value that was higher than any in
136 * the DB, wrap around and select the page with the
137 * lowest value instead! One might think this would
138 * skew the distribution, but in fact it won't cause
139 * any more bias than what the page_random scheme
140 * causes anyway. Trust me, I'm a mathematician. :)
141 */
142 if ( !$row ) {
143 $row = $this->selectRandomPageFromDB( "0", __METHOD__ );
144 }
145
146 if ( $row ) {
147 return Title::makeTitleSafe( $row->page_namespace, $row->page_title );
148 }
149
150 return null;
151 }
152
153 protected function getQueryInfo( $randstr ) {
154 $redirect = $this->isRedirect() ? 1 : 0;
155 $tables = [ 'page' ];
156 $conds = array_merge( [
157 'page_namespace' => $this->namespaces,
158 'page_is_redirect' => $redirect,
159 'page_random >= ' . $randstr
160 ], $this->extra );
161 $joinConds = [];
162
163 // Allow extensions to modify the query
164 $this->getHookRunner()->onRandomPageQuery( $tables, $conds, $joinConds );
165
166 return [
167 'tables' => $tables,
168 'fields' => [ 'page_title', 'page_namespace' ],
169 'conds' => $conds,
170 'options' => [
171 'ORDER BY' => 'page_random',
172 'LIMIT' => 1,
173 ],
174 'join_conds' => $joinConds
175 ];
176 }
177
178 private function selectRandomPageFromDB( $randstr, $fname = __METHOD__ ) {
179 $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
180
181 $query = $this->getQueryInfo( $randstr );
182 $res = $dbr->select(
183 $query['tables'],
184 $query['fields'],
185 $query['conds'],
186 $fname,
187 $query['options'],
188 $query['join_conds']
189 );
190
191 return $dbr->fetchObject( $res );
192 }
193
194 protected function getGroupName() {
195 return 'redirects';
196 }
197}
198
203class_alias( SpecialRandomPage::class, 'RandomPage' );
const NS_MAIN
Definition Defines.php:64
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
MediaWikiServices is the service locator for the application scope of MediaWiki.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Parent class for all special pages.
getName()
Get the name of this Special Page.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
getContentLanguage()
Shortcut to get content language.
Special page to direct the user to a random page.
ILoadBalancer $loadBalancer
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
execute( $par)
Default execute method Checks user permissions.
selectRandomPageFromDB( $randstr, $fname=__METHOD__)
getNsList()
Get a comma-delimited list of namespaces we don't have any pages in.
getRandomTitle()
Choose a random title.
__construct( $loadBalancer=null, NamespaceInfo $nsInfo=null)
Database cluster connection, tracking, load balancing, and transaction manager interface.