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