MediaWiki  master
SpecialRandompage.php
Go to the documentation of this file.
1 <?php
26 
32 class RandomPage extends SpecialPage {
33  private $namespaces; // namespaces to select pages from
34  protected $isRedir = false; // should the result be a redirect?
35  protected $extra = []; // Extra SQL statements
36 
37  public function __construct( $name = 'Randompage' ) {
38  $this->namespaces = MediaWikiServices::getInstance()->getNamespaceInfo()->
39  getContentNamespaces();
40  parent::__construct( $name );
41  }
42 
43  public function getNamespaces() {
44  return $this->namespaces;
45  }
46 
47  public function setNamespace( $ns ) {
48  if ( !$ns || $ns < NS_MAIN ) {
49  $ns = NS_MAIN;
50  }
51  $this->namespaces = [ $ns ];
52  }
53 
54  // select redirects instead of normal pages?
55  public function isRedirect() {
56  return $this->isRedir;
57  }
58 
59  public function execute( $par ) {
60  if ( is_string( $par ) ) {
61  // Testing for stringiness since we want to catch
62  // the empty string to mean main namespace only.
63  $this->setNamespace(
64  MediaWikiServices::getInstance()->getContentLanguage()->getNsIndex( $par ) );
65  }
66 
67  $title = $this->getRandomTitle();
68 
69  if ( is_null( $title ) ) {
70  $this->setHeaders();
71  // Message: randompage-nopages, randomredirect-nopages
72  $this->getOutput()->addWikiMsg( strtolower( $this->getName() ) . '-nopages',
73  $this->getNsList(), count( $this->namespaces ) );
74 
75  return;
76  }
77 
78  $redirectParam = $this->isRedirect() ? [ 'redirect' => 'no' ] : [];
79  $query = array_merge( $this->getRequest()->getValues(), $redirectParam );
80  unset( $query['title'] );
81  $this->getOutput()->redirect( $title->getFullURL( $query ) );
82  }
83 
89  private function getNsList() {
90  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
91  $nsNames = [];
92  foreach ( $this->namespaces as $n ) {
93  if ( $n === NS_MAIN ) {
94  $nsNames[] = $this->msg( 'blanknamespace' )->plain();
95  } else {
96  $nsNames[] = $contLang->getNsText( $n );
97  }
98  }
99 
100  return $contLang->commaList( $nsNames );
101  }
102 
107  public function getRandomTitle() {
108  $randstr = wfRandom();
109  $title = null;
110 
111  if ( !Hooks::run(
112  'SpecialRandomGetRandomTitle',
113  [ &$randstr, &$this->isRedir, &$this->namespaces, &$this->extra, &$title ]
114  ) ) {
115  return $title;
116  }
117 
118  $row = $this->selectRandomPageFromDB( $randstr );
119 
120  /* If we picked a value that was higher than any in
121  * the DB, wrap around and select the page with the
122  * lowest value instead! One might think this would
123  * skew the distribution, but in fact it won't cause
124  * any more bias than what the page_random scheme
125  * causes anyway. Trust me, I'm a mathematician. :)
126  */
127  if ( !$row ) {
128  $row = $this->selectRandomPageFromDB( "0" );
129  }
130 
131  if ( $row ) {
132  return Title::makeTitleSafe( $row->page_namespace, $row->page_title );
133  }
134 
135  return null;
136  }
137 
138  protected function getQueryInfo( $randstr ) {
139  $redirect = $this->isRedirect() ? 1 : 0;
140  $tables = [ 'page' ];
141  $conds = array_merge( [
142  'page_namespace' => $this->namespaces,
143  'page_is_redirect' => $redirect,
144  'page_random >= ' . $randstr
145  ], $this->extra );
146  $joinConds = [];
147 
148  // Allow extensions to modify the query
149  Hooks::run( 'RandomPageQuery', [ &$tables, &$conds, &$joinConds ] );
150 
151  return [
152  'tables' => $tables,
153  'fields' => [ 'page_title', 'page_namespace' ],
154  'conds' => $conds,
155  'options' => [
156  'ORDER BY' => 'page_random',
157  'LIMIT' => 1,
158  ],
159  'join_conds' => $joinConds
160  ];
161  }
162 
163  private function selectRandomPageFromDB( $randstr, $fname = __METHOD__ ) {
164  $dbr = wfGetDB( DB_REPLICA );
165 
166  $query = $this->getQueryInfo( $randstr );
167  $res = $dbr->select(
168  $query['tables'],
169  $query['fields'],
170  $query['conds'],
171  $fname,
172  $query['options'],
173  $query['join_conds']
174  );
175 
176  return $dbr->fetchObject( $res );
177  }
178 
179  protected function getGroupName() {
180  return 'redirects';
181  }
182 }
getQueryInfo( $randstr)
const NS_MAIN
Definition: Defines.php:60
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
getOutput()
Get the OutputPage being used for this instance.
getNsList()
Get a comma-delimited list of namespaces we don&#39;t have any pages in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRandomTitle()
Choose a random title.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes! ...
__construct( $name='Randompage')
selectRandomPageFromDB( $randstr, $fname=__METHOD__)
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:612
Special page to direct the user to a random page.
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
getName()
Get the name of this Special Page.
const DB_REPLICA
Definition: defines.php:25
getRequest()
Get the WebRequest being used for this instance.
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200