MediaWiki REL1_39
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
39 private $loadBalancer;
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
53 ? $loadBalancer
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 // @phan-suppress-next-line PhanTypeMismatchArgument Type mismatch on pass-by-ref args
129 $this->extra, $title )
130 ) {
131 return $title;
132 }
133
134 $row = $this->selectRandomPageFromDB( $randstr, __METHOD__ );
135
136 /* If we picked a value that was higher than any in
137 * the DB, wrap around and select the page with the
138 * lowest value instead! One might think this would
139 * skew the distribution, but in fact it won't cause
140 * any more bias than what the page_random scheme
141 * causes anyway. Trust me, I'm a mathematician. :)
142 */
143 if ( !$row ) {
144 $row = $this->selectRandomPageFromDB( "0", __METHOD__ );
145 }
146
147 if ( $row ) {
148 return Title::makeTitleSafe( $row->page_namespace, $row->page_title );
149 }
150
151 return null;
152 }
153
154 protected function getQueryInfo( $randstr ) {
155 $redirect = $this->isRedirect() ? 1 : 0;
156 $tables = [ 'page' ];
157 $conds = array_merge( [
158 'page_namespace' => $this->namespaces,
159 'page_is_redirect' => $redirect,
160 'page_random >= ' . $randstr
161 ], $this->extra );
162 $joinConds = [];
163
164 // Allow extensions to modify the query
165 $this->getHookRunner()->onRandomPageQuery( $tables, $conds, $joinConds );
166
167 return [
168 'tables' => $tables,
169 'fields' => [ 'page_title', 'page_namespace' ],
170 'conds' => $conds,
171 'options' => [
172 'ORDER BY' => 'page_random',
173 'LIMIT' => 1,
174 ],
175 'join_conds' => $joinConds
176 ];
177 }
178
179 private function selectRandomPageFromDB( $randstr, $fname = __METHOD__ ) {
180 $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
181
182 $query = $this->getQueryInfo( $randstr );
183 $res = $dbr->select(
184 $query['tables'],
185 $query['fields'],
186 $query['conds'],
187 $fname,
188 $query['options'],
189 $query['join_conds']
190 );
191
192 return $res->fetchObject();
193 }
194
195 protected function getGroupName() {
196 return 'redirects';
197 }
198}
199
204class_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 ...
Service locator for MediaWiki core services.
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.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
execute( $par)
Default execute method Checks user permissions.
getRandomTitle()
Choose a random title.
__construct( $loadBalancer=null, NamespaceInfo $nsInfo=null)
Create and track the database connections and transactions for a given database cluster.