128 [ $oldRels, $deleteCurrent ] = $this->
getOldRels();
130 if ( $deleteCurrent ) {
131 $hashes[
'.'] = $this->file->getSha1();
134 if ( count( $oldRels ) ) {
135 $dbw = $this->file->repo->getPrimaryDB();
138 [
'oi_archive_name',
'oi_sha1' ],
139 [
'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) ),
140 'oi_name' => $this->file->getName() ],
144 foreach (
$res as $row ) {
145 if ( rtrim( $row->oi_sha1,
"\0" ) ===
'' ) {
147 $oldUrl = $this->file->getArchiveVirtualUrl( $row->oi_archive_name );
148 $props = $this->file->repo->getFileProps( $oldUrl );
150 if ( $props[
'fileExists'] ) {
152 $dbw->update(
'oldimage',
153 [
'oi_sha1' => $props[
'sha1'] ],
154 [
'oi_name' => $this->file->getName(),
'oi_archive_name' => $row->oi_archive_name ],
156 $hashes[$row->oi_archive_name] = $props[
'sha1'];
158 $hashes[$row->oi_archive_name] =
false;
161 $hashes[$row->oi_archive_name] = $row->oi_sha1;
166 $missing = array_diff_key( $this->srcRels,
$hashes );
168 foreach ( $missing as $name => $rel ) {
169 $status->
error(
'filedelete-old-unregistered', $name );
172 foreach (
$hashes as $name => $hash ) {
174 $status->
error(
'filedelete-missing', $this->srcRels[$name] );
184 $dbw = $this->file->repo->getPrimaryDB();
186 $commentStore = MediaWikiServices::getInstance()->getCommentStore();
188 $encTimestamp = $dbw->addQuotes( $dbw->timestamp( $now ) );
189 $encUserId = $dbw->addQuotes( $this->user->getId() );
190 $encGroup = $dbw->addQuotes(
'deleted' );
191 $ext = $this->file->getExtension();
192 $dotExt =
$ext ===
'' ?
'' :
".$ext";
193 $encExt = $dbw->addQuotes( $dotExt );
194 [ $oldRels, $deleteCurrent ] = $this->getOldRels();
197 if ( $this->suppress ) {
198 $bitfield = RevisionRecord::SUPPRESSED_ALL;
200 $bitfield =
'oi_deleted';
203 if ( $deleteCurrent ) {
204 $tables = [
'image' ];
206 'fa_storage_group' => $encGroup,
207 'fa_storage_key' => $dbw->conditional(
208 [
'img_sha1' =>
'' ],
209 $dbw->addQuotes(
'' ),
210 $dbw->buildConcat( [
"img_sha1", $encExt ] )
212 'fa_deleted_user' => $encUserId,
213 'fa_deleted_timestamp' => $encTimestamp,
214 'fa_deleted' => $this->suppress ? $bitfield : 0,
215 'fa_name' =>
'img_name',
216 'fa_archive_name' =>
'NULL',
217 'fa_size' =>
'img_size',
218 'fa_width' =>
'img_width',
219 'fa_height' =>
'img_height',
220 'fa_metadata' =>
'img_metadata',
221 'fa_bits' =>
'img_bits',
222 'fa_media_type' =>
'img_media_type',
223 'fa_major_mime' =>
'img_major_mime',
224 'fa_minor_mime' =>
'img_minor_mime',
225 'fa_description_id' =>
'img_description_id',
226 'fa_timestamp' =>
'img_timestamp',
227 'fa_sha1' =>
'img_sha1',
228 'fa_actor' =>
'img_actor',
232 $fields += array_map(
233 [ $dbw,
'addQuotes' ],
234 $commentStore->insert( $dbw,
'fa_deleted_reason', $this->reason )
237 $dbw->insertSelect(
'filearchive', $tables, $fields,
238 [
'img_name' => $this->file->getName() ], __METHOD__, [], [], $joins );
241 if ( count( $oldRels ) ) {
242 $fileQuery = OldLocalFile::getQueryInfo();
244 $fileQuery[
'tables'],
245 $fileQuery[
'fields'],
247 'oi_name' => $this->file->getName(),
248 'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) )
255 if (
$res->numRows() ) {
256 $reason = $commentStore->createComment( $dbw, $this->reason );
257 foreach (
$res as $row ) {
258 $comment = $commentStore->getComment(
'oi_description', $row );
261 'fa_storage_group' =>
'deleted',
262 'fa_storage_key' => ( $row->oi_sha1 ===
'' )
264 :
"{$row->oi_sha1}{$dotExt}",
265 'fa_deleted_user' => $this->user->getId(),
266 'fa_deleted_timestamp' => $dbw->timestamp( $now ),
268 'fa_deleted' => $this->suppress ? $bitfield : $row->oi_deleted,
269 'fa_name' => $row->oi_name,
270 'fa_archive_name' => $row->oi_archive_name,
271 'fa_size' => $row->oi_size,
272 'fa_width' => $row->oi_width,
273 'fa_height' => $row->oi_height,
274 'fa_metadata' => $row->oi_metadata,
275 'fa_bits' => $row->oi_bits,
276 'fa_media_type' => $row->oi_media_type,
277 'fa_major_mime' => $row->oi_major_mime,
278 'fa_minor_mime' => $row->oi_minor_mime,
279 'fa_actor' => $row->oi_actor,
280 'fa_timestamp' => $row->oi_timestamp,
281 'fa_sha1' => $row->oi_sha1
282 ] + $commentStore->insert( $dbw,
'fa_deleted_reason', $reason )
283 + $commentStore->insert( $dbw,
'fa_description', $comment );
287 $dbw->insert(
'filearchive', $rowsInsert, __METHOD__ );
313 $repo = $this->file->getRepo();
314 $lockStatus = $this->file->acquireFileLock();
315 if ( !$lockStatus->isOK() ) {
318 $unlockScope =
new ScopedCallback(
function () {
319 $this->file->releaseFileLock();
322 $status = $this->file->repo->
newGood();
324 $hashes = $this->getHashes( $status );
325 $this->deletionBatch = [];
326 $ext = $this->file->getExtension();
327 $dotExt =
$ext ===
'' ?
'' :
".$ext";
329 foreach ( $this->srcRels as $name => $srcRel ) {
331 if ( isset(
$hashes[$name] ) ) {
333 $key = $hash . $dotExt;
334 $dstRel = $repo->getDeletedHashPath( $key ) . $key;
335 $this->deletionBatch[$name] = [ $srcRel, $dstRel ];
339 if ( !$repo->hasSha1Storage() ) {
342 $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch );
343 if ( !$checkStatus->isGood() ) {
344 $status->merge( $checkStatus );
347 $this->deletionBatch = $checkStatus->value;
350 $status = $this->file->repo->deleteBatch( $this->deletionBatch );
351 if ( !$status->isGood() ) {
352 $status->merge( $status );
356 if ( !$status->isOK() ) {
361 $dbw = $this->file->repo->getPrimaryDB();
363 $dbw->startAtomic( __METHOD__ );
366 $this->doDBInserts();
368 $this->doDBDeletes();
372 $dbw->endAtomic( __METHOD__ );
375 ScopedCallback::consume( $unlockScope );
388 foreach ( $batch as [ $src, ] ) {
389 $files[$src] = $this->file->repo->getVirtualUrl(
'public' ) .
'/' . rawurlencode( $src );
392 $result = $this->file->repo->fileExistsBatch( $files );
393 if ( in_array(
null, $result,
true ) ) {
394 return Status::newFatal(
'backend-fail-internal',
395 $this->file->repo->getBackend()->getName() );
399 foreach ( $batch as $batchItem ) {
400 if ( $result[$batchItem[0]] ) {
401 $newBatch[] = $batchItem;
405 return Status::newGood( $newBatch );