MediaWiki  master
SpecialRandompage.php
Go to the documentation of this file.
1 <?php
27 
33 class RandomPage extends SpecialPage {
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
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 }
RandomPage\$isRedir
$isRedir
Definition: SpecialRandompage.php:35
RandomPage\execute
execute( $par)
Default execute method Checks user permissions.
Definition: SpecialRandompage.php:75
RandomPage\setNamespace
setNamespace( $ns)
Definition: SpecialRandompage.php:63
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:911
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:789
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:173
RandomPage\isRedirect
isRedirect()
Definition: SpecialRandompage.php:71
$res
$res
Definition: testCompression.php:57
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:179
NS_MAIN
const NS_MAIN
Definition: Defines.php:64
$dbr
$dbr
Definition: testCompression.php:54
SpecialPage\getHookRunner
getHookRunner()
Definition: SpecialPage.php:1094
RandomPage\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialRandompage.php:194
RandomPage\selectRandomPageFromDB
selectRandomPageFromDB( $randstr, $fname=__METHOD__)
Definition: SpecialRandompage.php:178
RandomPage\getNsList
getNsList()
Get a comma-delimited list of namespaces we don't have any pages in.
Definition: SpecialRandompage.php:104
$title
$title
Definition: testCompression.php:38
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:617
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
RandomPage\__construct
__construct( $loadBalancer=null, NamespaceInfo $nsInfo=null)
Definition: SpecialRandompage.php:45
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:652
RandomPage\getNamespaces
getNamespaces()
Definition: SpecialRandompage.php:59
RandomPage\$extra
$extra
Definition: SpecialRandompage.php:36
SpecialPage
Parent class for all special pages.
Definition: SpecialPage.php:43
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:779
RandomPage\$namespaces
$namespaces
Definition: SpecialRandompage.php:34
wfRandom
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
Definition: GlobalFunctions.php:260
RandomPage\getRandomTitle
getRandomTitle()
Choose a random title.
Definition: SpecialRandompage.php:122
NamespaceInfo
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Definition: NamespaceInfo.php:35
SpecialPage\getContentLanguage
getContentLanguage()
Shortcut to get content language.
Definition: SpecialPage.php:839
RandomPage
Special page to direct the user to a random page.
Definition: SpecialRandompage.php:33
RandomPage\getQueryInfo
getQueryInfo( $randstr)
Definition: SpecialRandompage.php:153
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
RandomPage\$loadBalancer
ILoadBalancer $loadBalancer
Definition: SpecialRandompage.php:39