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.
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.
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
22 namespace MediaWiki\Pager
;
25 use ImageGalleryClassNotFoundException
;
26 use MediaWiki\Cache\LinkBatchFactory
;
27 use MediaWiki\Context\IContextSource
;
28 use MediaWiki\Html\FormOptions
;
29 use MediaWiki\Linker\LinkRenderer
;
30 use MediaWiki\Permissions\GroupPermissionsLookup
;
31 use MediaWiki\Title\Title
;
32 use MediaWiki\Title\TitleValue
;
33 use MediaWiki\User\ExternalUserNames
;
35 use Wikimedia\Rdbms\IConnectionProvider
;
40 class NewFilesPager
extends RangeChronologicalPager
{
43 * @var ImageGalleryBase
52 private GroupPermissionsLookup
$groupPermissionsLookup;
53 private LinkBatchFactory
$linkBatchFactory;
56 * @param IContextSource $context
57 * @param GroupPermissionsLookup $groupPermissionsLookup
58 * @param LinkBatchFactory $linkBatchFactory
59 * @param LinkRenderer $linkRenderer
60 * @param IConnectionProvider $dbProvider
61 * @param FormOptions $opts
63 public function __construct(
64 IContextSource
$context,
65 GroupPermissionsLookup
$groupPermissionsLookup,
66 LinkBatchFactory
$linkBatchFactory,
67 LinkRenderer
$linkRenderer,
68 IConnectionProvider
$dbProvider,
71 // Set database before parent constructor to avoid setting it there
72 $this->mDb
= $dbProvider->getReplicaDatabase();
74 parent
::__construct( $context, $linkRenderer );
77 $this->groupPermissionsLookup
= $groupPermissionsLookup;
78 $this->linkBatchFactory
= $linkBatchFactory;
79 $this->setLimit( $opts->getValue( 'limit' ) );
83 if ( $opts->getValue( 'start' ) ) {
84 $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
86 if ( $opts->getValue( 'end' ) ) {
87 $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
89 $this->getDateRangeCond( $startTimestamp, $endTimestamp );
92 public function getQueryInfo() {
95 $dbr = $this->getDatabase();
96 $tables = [ 'image', 'actor' ];
97 $fields = [ 'img_name', 'img_timestamp', 'actor_user', 'actor_name' ];
99 $jconds = [ 'actor' => [ 'JOIN', 'actor_id=img_actor' ] ];
101 $user = $opts->getValue( 'user' );
102 if ( $user !== '' ) {
103 $conds['actor_name'] = $user;
106 if ( !$opts->getValue( 'showbots' ) ) {
107 $groupsWithBotPermission = $this->groupPermissionsLookup
->getGroupsWithPermission( 'bot' );
109 if ( count( $groupsWithBotPermission ) ) {
110 $tables[] = 'user_groups';
111 $conds['ug_group'] = null;
112 $jconds['user_groups'] = [
115 'ug_group' => $groupsWithBotPermission,
116 'ug_user = actor_user',
117 $dbr->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $dbr->timestamp() )
123 if ( $opts->getValue( 'hidepatrolled' ) ) {
124 $tables[] = 'recentchanges';
125 $conds['rc_type'] = RC_LOG
;
126 $conds['rc_log_type'] = 'upload';
127 $conds['rc_patrolled'] = RecentChange
::PRC_UNPATROLLED
;
128 $conds['rc_namespace'] = NS_FILE
;
130 $jconds['recentchanges'] = [
133 'rc_title = img_name',
134 'rc_actor = img_actor',
135 'rc_timestamp = img_timestamp'
140 if ( $opts->getValue( 'mediatype' ) ) {
141 $conds['img_media_type'] = $opts->getValue( 'mediatype' );
144 // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first
145 // and filesort the result set later.
146 // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533
147 // Twist: This would cause issues if the user is set and we need to check user existence first
148 if ( $user === '' ) {
149 $options[] = 'STRAIGHT_JOIN';
155 'join_conds' => $jconds,
157 'options' => $options,
163 public function getIndexField() {
164 return [ [ 'img_timestamp', 'img_name' ] ];
167 protected function getStartBody() {
168 if ( !$this->gallery
) {
169 // Note that null for mode is taken to mean use default.
170 $mode = $this->getRequest()->getVal( 'gallerymode', null );
172 $this->gallery
= ImageGalleryBase
::factory( $mode, $this->getContext() );
173 } catch ( ImageGalleryClassNotFoundException
$e ) {
174 // User specified something invalid, fallback to default.
175 $this->gallery
= ImageGalleryBase
::factory( false, $this->getContext() );
182 protected function getEndBody() {
183 return $this->gallery
->toHTML();
186 protected function doBatchLookups() {
187 $this->mResult
->seek( 0 );
188 $lb = $this->linkBatchFactory
->newLinkBatch();
189 foreach ( $this->mResult
as $row ) {
190 if ( $row->actor_user
) {
191 $lb->add( NS_USER
, $row->actor_name
);
197 public function formatRow( $row ) {
198 $username = $row->actor_name
;
200 if ( ExternalUserNames
::isExternal( $username ) ) {
201 $ul = htmlspecialchars( $username );
203 $ul = $this->getLinkRenderer()->makeLink(
204 new TitleValue( NS_USER
, $username ),
208 $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp
, $this->getUser() );
211 Title
::makeTitle( NS_FILE
, $row->img_name
),
213 . htmlspecialchars( $time )
218 ImageGalleryBase
::LOADING_LAZY
226 * Retain the old class name for backwards compatibility.
227 * @deprecated since 1.41
229 class_alias( NewFilesPager
::class, 'NewFilesPager' );