1<?php 2/** 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * http://www.gnu.org/copyleft/gpl.html 17 * 18 * @file 19 * @ingroup Pager 20 */ 21 22use MediaWiki\Cache\LinkBatchFactory; 23use MediaWiki\HookContainer\HookContainer; 24use MediaWiki\HookContainer\HookRunner; 25use MediaWiki\Permissions\GroupPermissionsLookup; 26use Wikimedia\Rdbms\ILoadBalancer; 27 28/** 29 * @ingroup Pager 30 */ 31class NewPagesPager extends ReverseChronologicalPager { 32 33 /** 34 * @var FormOptions 35 */ 36 protected $opts; 37 38 /** 39 * @var SpecialNewpages 40 */ 41 protected $mForm; 42 43 /** @var LinkBatchFactory */ 44 private $linkBatchFactory; 45 46 /** @var HookRunner */ 47 private $hookRunner; 48 49 /** @var GroupPermissionsLookup */ 50 private $groupPermissionsLookup; 51 52 /** @var NamespaceInfo */ 53 private $namespaceInfo; 54 55 /** 56 * @param SpecialNewpages $form 57 * @param FormOptions $opts 58 * @param LinkBatchFactory $linkBatchFactory 59 * @param HookContainer $hookContainer 60 * @param GroupPermissionsLookup $groupPermissionsLookup 61 * @param ILoadBalancer $loadBalancer 62 * @param NamespaceInfo $namespaceInfo 63 */ 64 public function __construct( 65 $form, 66 FormOptions $opts, 67 LinkBatchFactory $linkBatchFactory, 68 HookContainer $hookContainer, 69 GroupPermissionsLookup $groupPermissionsLookup, 70 ILoadBalancer $loadBalancer, 71 NamespaceInfo $namespaceInfo 72 ) { 73 // Set database before parent constructor to avoid setting it there with wfGetDB 74 $this->mDb = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); 75 parent::__construct( $form->getContext() ); 76 $this->mForm = $form; 77 $this->opts = $opts; 78 $this->linkBatchFactory = $linkBatchFactory; 79 $this->hookRunner = new HookRunner( $hookContainer ); 80 $this->groupPermissionsLookup = $groupPermissionsLookup; 81 $this->namespaceInfo = $namespaceInfo; 82 } 83 84 public function getQueryInfo() { 85 $rcQuery = RecentChange::getQueryInfo(); 86 87 $conds = []; 88 $conds['rc_new'] = 1; 89 90 $username = $this->opts->getValue( 'username' ); 91 $user = Title::makeTitleSafe( NS_USER, $username ); 92 93 $size = abs( intval( $this->opts->getValue( 'size' ) ) ); 94 if ( $size > 0 ) { 95 if ( $this->opts->getValue( 'size-mode' ) === 'max' ) { 96 $conds[] = 'page_len <= ' . $size; 97 } else { 98 $conds[] = 'page_len >= ' . $size; 99 } 100 } 101 102 if ( $user ) { 103 $conds['actor_name'] = $user->getText(); 104 } elseif ( $this->canAnonymousUsersCreatePages() && $this->opts->getValue( 'hideliu' ) ) { 105 # If anons cannot make new pages, don't "exclude logged in users"! 106 $conds['actor_user'] = null; 107 } 108 109 $conds = array_merge( $conds, $this->getNamespaceCond() ); 110 111 # If this user cannot see patrolled edits or they are off, don't do dumb queries! 112 if ( $this->opts->getValue( 'hidepatrolled' ) && $this->getUser()->useNPPatrol() ) { 113 $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED; 114 } 115 116 if ( $this->opts->getValue( 'hidebots' ) ) { 117 $conds['rc_bot'] = 0; 118 } 119 120 if ( $this->opts->getValue( 'hideredirs' ) ) { 121 $conds['page_is_redirect'] = 0; 122 } 123 124 // Allow changes to the New Pages query 125 $tables = array_merge( $rcQuery['tables'], [ 'page' ] ); 126 $fields = array_merge( $rcQuery['fields'], [ 127 'length' => 'page_len', 'rev_id' => 'page_latest', 'page_namespace', 'page_title', 128 'page_content_model', 129 ] ); 130 $join_conds = [ 'page' => [ 'JOIN', 'page_id=rc_cur_id' ] ] + $rcQuery['joins']; 131 132 $this->hookRunner->onSpecialNewpagesConditions( 133 $this, $this->opts, $conds, $tables, $fields, $join_conds ); 134 135 $info = [ 136 'tables' => $tables, 137 'fields' => $fields, 138 'conds' => $conds, 139 'options' => [], 140 'join_conds' => $join_conds 141 ]; 142 143 // Modify query for tags 144 ChangeTags::modifyDisplayQuery( 145 $info['tables'], 146 $info['fields'], 147 $info['conds'], 148 $info['join_conds'], 149 $info['options'], 150 $this->opts['tagfilter'] 151 ); 152 153 return $info; 154 } 155 156 private function canAnonymousUsersCreatePages() { 157 return $this->groupPermissionsLookup->groupHasPermission( '*', 'createpage' ) || 158 $this->groupPermissionsLookup->groupHasPermission( '*', 'createtalk' ); 159 } 160 161 // Based on ContribsPager.php 162 private function getNamespaceCond() { 163 $namespace = $this->opts->getValue( 'namespace' ); 164 if ( $namespace === 'all' || $namespace === '' ) { 165 return []; 166 } 167 168 $namespace = intval( $namespace ); 169 if ( $namespace < NS_MAIN ) { 170 // Negative namespaces are invalid 171 return []; 172 } 173 174 $invert = $this->opts->getValue( 'invert' ); 175 $associated = $this->opts->getValue( 'associated' ); 176 177 $eq_op = $invert ? '!=' : '='; 178 $bool_op = $invert ? 'AND' : 'OR'; 179 180 $dbr = $this->getDatabase(); 181 $selectedNS = $dbr->addQuotes( $namespace ); 182 if ( !$associated ) { 183 return [ "rc_namespace $eq_op $selectedNS" ]; 184 } 185 186 $associatedNS = $dbr->addQuotes( 187 $this->namespaceInfo->getAssociated( $namespace ) 188 ); 189 return [ 190 "rc_namespace $eq_op $selectedNS " . 191 $bool_op . 192 " rc_namespace $eq_op $associatedNS" 193 ]; 194 } 195 196 public function getIndexField() { 197 return 'rc_timestamp'; 198 } 199 200 public function formatRow( $row ) { 201 return $this->mForm->formatRow( $row ); 202 } 203 204 protected function getStartBody() { 205 # Do a batch existence check on pages 206 $linkBatch = $this->linkBatchFactory->newLinkBatch(); 207 foreach ( $this->mResult as $row ) { 208 $linkBatch->add( NS_USER, $row->rc_user_text ); 209 $linkBatch->add( NS_USER_TALK, $row->rc_user_text ); 210 $linkBatch->add( $row->page_namespace, $row->page_title ); 211 } 212 $linkBatch->execute(); 213 214 return '<ul>'; 215 } 216 217 protected function getEndBody() { 218 return '</ul>'; 219 } 220} 221