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\Linker\LinkRenderer; 24use MediaWiki\Permissions\GroupPermissionsLookup; 25use Wikimedia\Rdbms\ILoadBalancer; 26 27/** 28 * @ingroup Pager 29 */ 30class NewFilesPager extends RangeChronologicalPager { 31 32 /** 33 * @var ImageGalleryBase 34 */ 35 protected $gallery; 36 37 /** 38 * @var FormOptions 39 */ 40 protected $opts; 41 42 /** @var GroupPermissionsLookup */ 43 private $groupPermissionsLookup; 44 45 /** @var LinkBatchFactory */ 46 private $linkBatchFactory; 47 48 /** 49 * @param IContextSource $context 50 * @param FormOptions $opts 51 * @param LinkRenderer $linkRenderer 52 * @param GroupPermissionsLookup $groupPermissionsLookup 53 * @param ILoadBalancer $loadBalancer 54 * @param LinkBatchFactory $linkBatchFactory 55 */ 56 public function __construct( 57 IContextSource $context, 58 FormOptions $opts, 59 LinkRenderer $linkRenderer, 60 GroupPermissionsLookup $groupPermissionsLookup, 61 ILoadBalancer $loadBalancer, 62 LinkBatchFactory $linkBatchFactory 63 ) { 64 // Set database before parent constructor to avoid setting it there with wfGetDB 65 $this->mDb = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); 66 67 parent::__construct( $context, $linkRenderer ); 68 69 $this->opts = $opts; 70 $this->groupPermissionsLookup = $groupPermissionsLookup; 71 $this->linkBatchFactory = $linkBatchFactory; 72 $this->setLimit( $opts->getValue( 'limit' ) ); 73 74 $startTimestamp = ''; 75 $endTimestamp = ''; 76 if ( $opts->getValue( 'start' ) ) { 77 $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00'; 78 } 79 if ( $opts->getValue( 'end' ) ) { 80 $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59'; 81 } 82 $this->getDateRangeCond( $startTimestamp, $endTimestamp ); 83 } 84 85 public function getQueryInfo() { 86 $opts = $this->opts; 87 $conds = []; 88 $dbr = $this->getDatabase(); 89 $tables = [ 'image', 'actor' ]; 90 $fields = [ 'img_name', 'img_timestamp', 'actor_user', 'actor_name' ]; 91 $options = []; 92 $jconds = [ 'actor' => [ 'JOIN', 'actor_id=img_actor' ] ]; 93 94 $user = $opts->getValue( 'user' ); 95 if ( $user !== '' ) { 96 $conds['actor_name'] = $user; 97 } 98 99 if ( !$opts->getValue( 'showbots' ) ) { 100 $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' ); 101 102 if ( count( $groupsWithBotPermission ) ) { 103 $tables[] = 'user_groups'; 104 $conds[] = 'ug_group IS NULL'; 105 $jconds['user_groups'] = [ 106 'LEFT JOIN', 107 [ 108 'ug_group' => $groupsWithBotPermission, 109 'ug_user = actor_user', 110 'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() ) 111 ] 112 ]; 113 } 114 } 115 116 if ( $opts->getValue( 'hidepatrolled' ) ) { 117 $tables[] = 'recentchanges'; 118 $conds['rc_type'] = RC_LOG; 119 $conds['rc_log_type'] = 'upload'; 120 $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED; 121 $conds['rc_namespace'] = NS_FILE; 122 123 $jconds['recentchanges'] = [ 124 'JOIN', 125 [ 126 'rc_title = img_name', 127 'rc_actor = img_actor', 128 'rc_timestamp = img_timestamp' 129 ] 130 ]; 131 } 132 133 if ( $opts->getValue( 'mediatype' ) ) { 134 $conds['img_media_type'] = $opts->getValue( 'mediatype' ); 135 } 136 137 $likeVal = $opts->getValue( 'like' ); 138 if ( !$this->getConfig()->get( 'MiserMode' ) && $likeVal !== '' ) { 139 $likeObj = Title::newFromText( $likeVal ); 140 if ( $likeObj instanceof Title ) { 141 $like = $dbr->buildLike( 142 $dbr->anyString(), 143 strtolower( $likeObj->getDBkey() ), 144 $dbr->anyString() 145 ); 146 $conds[] = "LOWER(img_name) $like"; 147 } 148 } 149 150 // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first 151 // and filesort the result set later. 152 // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533 153 $options[] = 'STRAIGHT_JOIN'; 154 155 $query = [ 156 'tables' => $tables, 157 'fields' => $fields, 158 'join_conds' => $jconds, 159 'conds' => $conds, 160 'options' => $options, 161 ]; 162 163 return $query; 164 } 165 166 public function getIndexField() { 167 return 'img_timestamp'; 168 } 169 170 protected function getStartBody() { 171 if ( !$this->gallery ) { 172 // Note that null for mode is taken to mean use default. 173 $mode = $this->getRequest()->getVal( 'gallerymode', null ); 174 try { 175 $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() ); 176 } catch ( Exception $e ) { 177 // User specified something invalid, fallback to default. 178 $this->gallery = ImageGalleryBase::factory( false, $this->getContext() ); 179 } 180 } 181 182 return ''; 183 } 184 185 protected function getEndBody() { 186 return $this->gallery->toHTML(); 187 } 188 189 protected function doBatchLookups() { 190 $this->mResult->seek( 0 ); 191 $lb = $this->linkBatchFactory->newLinkBatch(); 192 foreach ( $this->mResult as $row ) { 193 if ( $row->actor_user ) { 194 $lb->add( NS_USER, $row->actor_name ); 195 } 196 } 197 $lb->execute(); 198 } 199 200 public function formatRow( $row ) { 201 $username = $row->actor_name; 202 203 if ( ExternalUserNames::isExternal( $username ) ) { 204 $ul = htmlspecialchars( $username ); 205 } else { 206 $ul = $this->getLinkRenderer()->makeLink( 207 new TitleValue( NS_USER, $username ), 208 $username 209 ); 210 } 211 $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() ); 212 213 $this->gallery->add( 214 Title::makeTitle( NS_FILE, $row->img_name ), 215 "$ul<br />\n<i>" 216 . htmlspecialchars( $time ) 217 . "</i><br />\n", 218 '', 219 '', 220 [], 221 ImageGalleryBase::LOADING_LAZY 222 ); 223 224 return ''; 225 } 226} 227