Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 124
0.00% covered (danger)
0.00%
0 / 20
CRAP
0.00% covered (danger)
0.00%
0 / 1
RevDelFileItem
0.00% covered (danger)
0.00%
0 / 124
0.00% covered (danger)
0.00%
0 / 20
1122
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 initFile
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getIdField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTimestampField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAuthorIdField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAuthorNameField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAuthorActorField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 canView
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 canViewContent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getBits
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setBits
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 isDeleted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLink
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 getUserTools
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getComment
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 getHTML
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getApiData
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
30
 lock
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 unlock
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
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 RevisionDelete
20 */
21
22use MediaWiki\Api\ApiResult;
23use MediaWiki\Html\Html;
24use MediaWiki\Linker\Linker;
25use MediaWiki\MediaWikiServices;
26use MediaWiki\RevisionList\RevisionListBase;
27use MediaWiki\SpecialPage\SpecialPage;
28use Wikimedia\Rdbms\IConnectionProvider;
29
30/**
31 * Item class for an oldimage table row
32 */
33class RevDelFileItem extends RevDelItem {
34    /** @var RevDelFileList */
35    protected $list;
36    /** @var OldLocalFile */
37    protected $file;
38    protected IConnectionProvider $dbProvider;
39
40    public function __construct( RevisionListBase $list, $row ) {
41        parent::__construct( $list, $row );
42        $this->file = static::initFile( $list, $row );
43        $this->dbProvider = MediaWikiServices::getInstance()->getConnectionProvider();
44    }
45
46    /**
47     * Create file object from $row sourced from $list
48     *
49     * @param RevisionListBase $list
50     * @param mixed $row
51     * @return mixed
52     */
53    protected static function initFile( $list, $row ) {
54        return MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
55            ->newFileFromRow( $row );
56    }
57
58    public function getIdField() {
59        return 'oi_archive_name';
60    }
61
62    public function getTimestampField() {
63        return 'oi_timestamp';
64    }
65
66    public function getAuthorIdField() {
67        return 'oi_user';
68    }
69
70    public function getAuthorNameField() {
71        return 'oi_user_text';
72    }
73
74    public function getAuthorActorField() {
75        return 'oi_actor';
76    }
77
78    public function getId() {
79        $parts = explode( '!', $this->row->oi_archive_name );
80
81        return $parts[0];
82    }
83
84    public function canView() {
85        return $this->file->userCan( File::DELETED_RESTRICTED, $this->list->getAuthority() );
86    }
87
88    public function canViewContent() {
89        return $this->file->userCan( File::DELETED_FILE, $this->list->getAuthority() );
90    }
91
92    public function getBits() {
93        return $this->file->getVisibility();
94    }
95
96    public function setBits( $bits ) {
97        # Queue the file op
98        # @todo FIXME: Move to LocalFile.php
99        if ( $this->isDeleted() ) {
100            if ( $bits & File::DELETED_FILE ) {
101                # Still deleted
102            } else {
103                # Newly undeleted
104                $key = $this->file->getStorageKey();
105                $srcRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
106                $this->list->storeBatch[] = [
107                    $this->file->repo->getVirtualUrl( 'deleted' ) . '/' . $srcRel,
108                    'public',
109                    $this->file->getRel()
110                ];
111                $this->list->cleanupBatch[] = $key;
112            }
113        } elseif ( $bits & File::DELETED_FILE ) {
114            # Newly deleted
115            $key = $this->file->getStorageKey();
116            $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key;
117            $this->list->deleteBatch[] = [ $this->file->getRel(), $dstRel ];
118        }
119
120        # Do the database operations
121        $dbw = $this->dbProvider->getPrimaryDatabase();
122        $dbw->newUpdateQueryBuilder()
123            ->update( 'oldimage' )
124            ->set( [ 'oi_deleted' => $bits ] )
125            ->where( [
126                'oi_name' => $this->row->oi_name,
127                'oi_timestamp' => $this->row->oi_timestamp,
128                'oi_deleted' => $this->getBits()
129            ] )
130            ->caller( __METHOD__ )->execute();
131
132        return (bool)$dbw->affectedRows();
133    }
134
135    public function isDeleted() {
136        return $this->file->isDeleted( File::DELETED_FILE );
137    }
138
139    /**
140     * Get the link to the file.
141     * Overridden by RevDelArchivedFileItem.
142     * @return string
143     */
144    protected function getLink() {
145        $date = $this->list->getLanguage()->userTimeAndDate(
146            $this->file->getTimestamp(), $this->list->getUser() );
147
148        if ( !$this->isDeleted() ) {
149            # Regular files...
150            return Html::element( 'a', [ 'href' => $this->file->getUrl() ], $date );
151        }
152
153        # Hidden files...
154        if ( !$this->canViewContent() ) {
155            $link = htmlspecialchars( $date );
156        } else {
157            $link = $this->getLinkRenderer()->makeLink(
158                SpecialPage::getTitleFor( 'Revisiondelete' ),
159                $date,
160                [],
161                [
162                    'target' => $this->list->getPageName(),
163                    'file' => $this->file->getArchiveName(),
164                    'token' => $this->list->getUser()->getEditToken(
165                        $this->file->getArchiveName() )
166                ]
167            );
168        }
169
170        return '<span class="history-deleted">' . $link . '</span>';
171    }
172
173    /**
174     * Generate a user tool link cluster if the current user is allowed to view it
175     * @return string HTML
176     */
177    protected function getUserTools() {
178        $uploader = $this->file->getUploader( File::FOR_THIS_USER, $this->list->getAuthority() );
179        if ( $uploader ) {
180            $link = Linker::userLink( $uploader->getId(), $uploader->getName() ) .
181                Linker::userToolLinks( $uploader->getId(), $uploader->getName() );
182            return $link;
183        } else {
184            $link = $this->list->msg( 'rev-deleted-user' )->escaped();
185        }
186        if ( $this->file->isDeleted( File::DELETED_USER ) ) {
187            return '<span class="history-deleted">' . $link . '</span>';
188        }
189        return $link;
190    }
191
192    /**
193     * Wrap and format the file's comment block, if the current
194     * user is allowed to view it.
195     *
196     * @return string HTML
197     */
198    protected function getComment() {
199        if ( $this->file->userCan( File::DELETED_COMMENT, $this->list->getAuthority() ) ) {
200            $block = MediaWikiServices::getInstance()->getCommentFormatter()
201                ->formatBlock( $this->file->getDescription() );
202        } else {
203            $block = ' ' . $this->list->msg( 'rev-deleted-comment' )->escaped();
204        }
205        if ( $this->file->isDeleted( File::DELETED_COMMENT ) ) {
206            return "<span class=\"history-deleted\">$block</span>";
207        }
208
209        return $block;
210    }
211
212    public function getHTML() {
213        $data =
214            $this->list->msg( 'widthheight' )->numParams(
215                $this->file->getWidth(),
216                $this->file->getHeight() )->escaped() .
217            ' (' . $this->list->msg( 'nbytes' )->numParams(
218                $this->file->getSize() )->escaped() . ')';
219
220        return '<li>' . $this->getLink() . ' ' . $this->getUserTools() . ' ' .
221            $data . ' ' . $this->getComment() . '</li>';
222    }
223
224    public function getApiData( ApiResult $result ) {
225        $file = $this->file;
226        $user = $this->list->getUser();
227        $ret = [
228            'title' => $this->list->getPageName(),
229            'archivename' => $file->getArchiveName(),
230            'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() ),
231            'width' => $file->getWidth(),
232            'height' => $file->getHeight(),
233            'size' => $file->getSize(),
234            'userhidden' => (bool)$file->isDeleted( File::DELETED_USER ),
235            'commenthidden' => (bool)$file->isDeleted( File::DELETED_COMMENT ),
236            'contenthidden' => (bool)$this->isDeleted(),
237        ];
238        if ( !$this->isDeleted() ) {
239            $ret += [
240                'url' => $file->getUrl(),
241            ];
242        } elseif ( $this->canViewContent() ) {
243            $ret += [
244                'url' => SpecialPage::getTitleFor( 'Revisiondelete' )->getLinkURL(
245                    [
246                        'target' => $this->list->getPageName(),
247                        'file' => $file->getArchiveName(),
248                        'token' => $user->getEditToken( $file->getArchiveName() )
249                    ]
250                ),
251            ];
252        }
253        $uploader = $file->getUploader( File::FOR_THIS_USER, $user );
254        if ( $uploader ) {
255            $ret += [
256                'userid' => $uploader->getId(),
257                'user' => $uploader->getName(),
258            ];
259        }
260        $comment = $file->getDescription( File::FOR_THIS_USER, $user );
261        if ( ( $comment ?? '' ) !== '' ) {
262            $ret += [
263                'comment' => $comment,
264            ];
265        }
266
267        return $ret;
268    }
269
270    public function lock() {
271        return $this->file->acquireFileLock();
272    }
273
274    public function unlock() {
275        return $this->file->releaseFileLock();
276    }
277}