Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 96
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
NewFilesPager
0.00% covered (danger)
0.00%
0 / 95
0.00% covered (danger)
0.00%
0 / 7
420
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getQueryInfo
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
56
 getIndexField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getStartBody
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 getEndBody
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doBatchLookups
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 formatRow
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
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
22namespace MediaWiki\Pager;
23
24use ImageGalleryBase;
25use ImageGalleryClassNotFoundException;
26use MediaWiki\Cache\LinkBatchFactory;
27use MediaWiki\Context\IContextSource;
28use MediaWiki\Html\FormOptions;
29use MediaWiki\Linker\LinkRenderer;
30use MediaWiki\Permissions\GroupPermissionsLookup;
31use MediaWiki\Title\Title;
32use MediaWiki\Title\TitleValue;
33use MediaWiki\User\ExternalUserNames;
34use RecentChange;
35use Wikimedia\Rdbms\IConnectionProvider;
36
37/**
38 * @ingroup Pager
39 */
40class NewFilesPager extends RangeChronologicalPager {
41
42    /**
43     * @var ImageGalleryBase
44     */
45    protected $gallery;
46
47    /**
48     * @var FormOptions
49     */
50    protected $opts;
51
52    private GroupPermissionsLookup $groupPermissionsLookup;
53    private LinkBatchFactory $linkBatchFactory;
54
55    /**
56     * @param IContextSource $context
57     * @param GroupPermissionsLookup $groupPermissionsLookup
58     * @param LinkBatchFactory $linkBatchFactory
59     * @param LinkRenderer $linkRenderer
60     * @param IConnectionProvider $dbProvider
61     * @param FormOptions $opts
62     */
63    public function __construct(
64        IContextSource $context,
65        GroupPermissionsLookup $groupPermissionsLookup,
66        LinkBatchFactory $linkBatchFactory,
67        LinkRenderer $linkRenderer,
68        IConnectionProvider $dbProvider,
69        FormOptions $opts
70    ) {
71        // Set database before parent constructor to avoid setting it there
72        $this->mDb = $dbProvider->getReplicaDatabase();
73
74        parent::__construct( $context, $linkRenderer );
75
76        $this->opts = $opts;
77        $this->groupPermissionsLookup = $groupPermissionsLookup;
78        $this->linkBatchFactory = $linkBatchFactory;
79        $this->setLimit( $opts->getValue( 'limit' ) );
80
81        $startTimestamp = '';
82        $endTimestamp = '';
83        if ( $opts->getValue( 'start' ) ) {
84            $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
85        }
86        if ( $opts->getValue( 'end' ) ) {
87            $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
88        }
89        $this->getDateRangeCond( $startTimestamp, $endTimestamp );
90    }
91
92    public function getQueryInfo() {
93        $opts = $this->opts;
94        $conds = [];
95        $dbr = $this->getDatabase();
96        $tables = [ 'image', 'actor' ];
97        $fields = [ 'img_name', 'img_timestamp', 'actor_user', 'actor_name' ];
98        $options = [];
99        $jconds = [ 'actor' => [ 'JOIN', 'actor_id=img_actor' ] ];
100
101        $user = $opts->getValue( 'user' );
102        if ( $user !== '' ) {
103            $conds['actor_name'] = $user;
104        }
105
106        if ( !$opts->getValue( 'showbots' ) ) {
107            $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' );
108
109            if ( count( $groupsWithBotPermission ) ) {
110                $tables[] = 'user_groups';
111                $conds['ug_group'] = null;
112                $jconds['user_groups'] = [
113                    'LEFT JOIN',
114                    [
115                        'ug_group' => $groupsWithBotPermission,
116                        'ug_user = actor_user',
117                        $dbr->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $dbr->timestamp() )
118                    ]
119                ];
120            }
121        }
122
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;
129
130            $jconds['recentchanges'] = [
131                'JOIN',
132                [
133                    'rc_title = img_name',
134                    'rc_actor = img_actor',
135                    'rc_timestamp = img_timestamp'
136                ]
137            ];
138        }
139
140        if ( $opts->getValue( 'mediatype' ) ) {
141            $conds['img_media_type'] = $opts->getValue( 'mediatype' );
142        }
143
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';
150        }
151
152        $query = [
153            'tables' => $tables,
154            'fields' => $fields,
155            'join_conds' => $jconds,
156            'conds' => $conds,
157            'options' => $options,
158        ];
159
160        return $query;
161    }
162
163    public function getIndexField() {
164        return [ [ 'img_timestamp', 'img_name' ] ];
165    }
166
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 );
171            try {
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() );
176            }
177        }
178
179        return '';
180    }
181
182    protected function getEndBody() {
183        return $this->gallery->toHTML();
184    }
185
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 );
192            }
193        }
194        $lb->execute();
195    }
196
197    public function formatRow( $row ) {
198        $username = $row->actor_name;
199
200        if ( ExternalUserNames::isExternal( $username ) ) {
201            $ul = htmlspecialchars( $username );
202        } else {
203            $ul = $this->getLinkRenderer()->makeLink(
204                new TitleValue( NS_USER, $username ),
205                $username
206            );
207        }
208        $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
209
210        $this->gallery->add(
211            Title::makeTitle( NS_FILE, $row->img_name ),
212            "$ul<br />\n<i>"
213                . htmlspecialchars( $time )
214                . "</i><br />\n",
215            '',
216            '',
217            [],
218            ImageGalleryBase::LOADING_LAZY
219        );
220
221        return '';
222    }
223}
224
225/**
226 * Retain the old class name for backwards compatibility.
227 * @deprecated since 1.41
228 */
229class_alias( NewFilesPager::class, 'NewFilesPager' );