82 $dbw = $this->file->repo->getPrimaryDB();
87 $result = $dbw->newSelectQueryBuilder()
88 ->select( [
'oi_archive_name' ] )
90 ->where( [
'oi_name' => $this->file->getName() ] )
91 ->caller( __METHOD__ )->fetchResultSet();
93 $result = $dbw->newSelectQueryBuilder()
94 ->select( [
'oi_archive_name' =>
'fr_archive_name' ] )
95 ->from(
'filerevision' )
96 ->join(
'file',
null,
'fr_file = file_id' )
97 ->where( [
'file_name' => $this->file->getName(),
'file_deleted' => 0,
'file_latest != fr_id' ] )
98 ->caller( __METHOD__ )->fetchResultSet();
101 foreach ( $result as $row ) {
102 $this->
addOld( $row->oi_archive_name );
103 $archiveNames[] = $row->oi_archive_name;
106 return $archiveNames;
131 [ $oldRels, $deleteCurrent ] = $this->
getOldRels();
133 if ( $deleteCurrent ) {
134 $hashes[
'.'] = $this->file->getSha1();
140 if ( count( $oldRels ) ) {
141 $dbw = $this->file->repo->getPrimaryDB();
143 $res = $dbw->newSelectQueryBuilder()
144 ->select( [
'oi_archive_name',
'oi_sha1' ] )
147 'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) ),
148 'oi_name' => $this->file->getName()
150 ->caller( __METHOD__ )->fetchResultSet();
152 $res = $dbw->newSelectQueryBuilder()
154 'oi_archive_name' =>
'fr_archive_name',
155 'oi_sha1' =>
'fr_sha1'
157 ->from(
'filerevision' )
158 ->join(
'file',
null,
'fr_file = file_id' )
160 'fr_archive_name' => array_map(
'strval', array_keys( $oldRels ) ),
161 'file_name' => $this->file->getName(),
163 'file_latest != fr_id',
165 ->caller( __METHOD__ )->fetchResultSet();
168 foreach ( $res as $row ) {
169 if ( $row->oi_archive_name ===
'' ) {
171 $hashes[$row->oi_archive_name] =
false;
174 if ( rtrim( $row->oi_sha1,
"\0" ) ===
'' ) {
176 $oldUrl = $this->file->getArchiveVirtualUrl( $row->oi_archive_name );
177 $props = $this->file->repo->getFileProps( $oldUrl );
179 if ( $props[
'fileExists'] ) {
183 $dbw->newUpdateQueryBuilder()
184 ->update(
'oldimage' )
185 ->set( [
'oi_sha1' => $props[
'sha1'] ] )
187 'oi_name' => $this->file->getName(),
188 'oi_archive_name' => $row->oi_archive_name,
190 ->caller( __METHOD__ )->execute();
193 $dbw->newUpdateQueryBuilder()
194 ->update(
'filerevision' )
195 ->set( [
'fr_sha1' => $props[
'sha1'] ] )
197 'fr_file' => $this->file->getFileIdFromName(),
198 'fr_archive_name' => $row->oi_archive_name,
200 ->caller( __METHOD__ )->execute();
202 $hashes[$row->oi_archive_name] = $props[
'sha1'];
204 $hashes[$row->oi_archive_name] =
false;
207 $hashes[$row->oi_archive_name] = $row->oi_sha1;
212 $missing = array_diff_key( $this->srcRels, $hashes );
214 foreach ( $missing as $name => $rel ) {
215 $status->
error(
'filedelete-old-unregistered', $name );
218 foreach ( $hashes as $name => $hash ) {
220 $status->
error(
'filedelete-missing', $this->srcRels[$name] );
221 unset( $hashes[$name] );
230 $dbw = $this->file->repo->getPrimaryDB();
234 $encTimestamp = $dbw->addQuotes( $dbw->timestamp( $now ) );
235 $encUserId = $dbw->addQuotes( $this->user->getId() );
236 $encGroup = $dbw->addQuotes(
'deleted' );
237 $ext = $this->file->getExtension();
238 $dotExt = $ext ===
'' ?
'' :
".$ext";
239 $encExt = $dbw->addQuotes( $dotExt );
240 [ $oldRels, $deleteCurrent ] = $this->getOldRels();
243 if ( $this->suppress ) {
244 $bitfield = RevisionRecord::SUPPRESSED_ALL;
246 $bitfield =
'oi_deleted';
249 if ( $deleteCurrent ) {
254 $tables = [
'image' ];
256 'name' =>
'img_name',
257 'size' =>
'img_size',
258 'width' =>
'img_width',
259 'height' =>
'img_height',
260 'metadata' =>
'img_metadata',
261 'bits' =>
'img_bits',
262 'media_type' =>
'img_media_type',
263 'major_mime' =>
'img_major_mime',
264 'minor_mime' =>
'img_minor_mime',
265 'description_id' =>
'img_description_id',
266 'timestamp' =>
'img_timestamp',
267 'sha1' =>
'img_sha1',
268 'actor' =>
'img_actor',
270 $conds = [
'img_name' => $this->file->getName() ];
273 $tables = [
'file',
'filerevision',
'filetypes' ];
275 'name' =>
'file_name',
277 'width' =>
'fr_width',
278 'height' =>
'fr_height',
279 'metadata' =>
'fr_metadata',
281 'media_type' =>
'ft_media_type',
282 'major_mime' =>
'ft_major_mime',
283 'minor_mime' =>
'ft_minor_mime',
284 'description_id' =>
'fr_description_id',
285 'timestamp' =>
'fr_timestamp',
287 'actor' =>
'fr_actor',
289 $conds = [
'file_name' => $this->file->getName(),
'file_deleted' => 0 ];
291 'filerevision' => [
'JOIN',
'file_latest = fr_id' ],
292 'filetypes' => [
'JOIN',
'file_type = ft_id' ],
297 'fa_storage_group' => $encGroup,
298 'fa_storage_key' => $dbw->conditional(
299 [ $sourceFields[
'sha1'] =>
'' ],
300 $dbw->addQuotes(
'' ),
301 $dbw->buildConcat( [ $sourceFields[
'sha1'], $encExt ] )
303 'fa_deleted_user' => $encUserId,
304 'fa_deleted_timestamp' => $encTimestamp,
305 'fa_deleted' => $this->suppress ? $bitfield : 0,
306 'fa_archive_name' =>
'NULL',
308 foreach ( $sourceFields as $field => $sourceField ) {
309 $fields[
"fa_$field"] = $sourceField;
312 $fields += array_map(
313 $dbw->addQuotes( ... ),
314 $commentStore->insert( $dbw,
'fa_deleted_reason', $this->reason )
317 $dbw->insertSelect(
'filearchive', $tables, $fields,
318 $conds, __METHOD__, [
'IGNORE' ], [], $joins );
321 if ( count( $oldRels ) ) {
325 ->where( [
'oi_name' => $this->file->getName() ] )
326 ->andWhere( [
'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) ) ] );
327 $res = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
328 if ( $res->numRows() ) {
329 $reason = $commentStore->createComment( $dbw, $this->reason );
331 foreach ( $res as $row ) {
332 $comment = $commentStore->getComment(
'oi_description', $row );
335 'fa_storage_group' =>
'deleted',
336 'fa_storage_key' => ( $row->oi_sha1 ===
'' )
338 :
"{$row->oi_sha1}{$dotExt}",
339 'fa_deleted_user' => $this->user->getId(),
340 'fa_deleted_timestamp' => $dbw->timestamp( $now ),
342 'fa_deleted' => $this->suppress ? $bitfield : $row->oi_deleted,
343 'fa_name' => $row->oi_name,
344 'fa_archive_name' => $row->oi_archive_name,
345 'fa_size' => $row->oi_size,
346 'fa_width' => $row->oi_width,
347 'fa_height' => $row->oi_height,
348 'fa_metadata' => $row->oi_metadata,
349 'fa_bits' => $row->oi_bits,
350 'fa_media_type' => $row->oi_media_type,
351 'fa_major_mime' => $row->oi_major_mime,
352 'fa_minor_mime' => $row->oi_minor_mime,
353 'fa_actor' => $row->oi_actor,
354 'fa_timestamp' => $row->oi_timestamp,
355 'fa_sha1' => $row->oi_sha1
356 ] + $commentStore->insert( $dbw,
'fa_deleted_reason', $reason )
357 + $commentStore->insert( $dbw,
'fa_description', $comment );
359 $dbw->newInsertQueryBuilder()
360 ->insertInto(
'filearchive' )
362 ->rows( $rowsInsert )
363 ->caller( __METHOD__ )->execute();
433 $repo = $this->file->getRepo();
434 $lockStatus = $this->file->acquireFileLock();
435 if ( !$lockStatus->isOK() ) {
438 $unlockScope =
new ScopedCallback(
function () {
439 $this->file->releaseFileLock();
442 $status = $this->file->repo->
newGood();
444 $hashes = $this->getHashes( $status );
445 $this->deletionBatch = [];
446 $ext = $this->file->getExtension();
447 $dotExt = $ext ===
'' ?
'' :
".$ext";
449 foreach ( $this->srcRels as $name => $srcRel ) {
451 if ( isset( $hashes[$name] ) ) {
452 $hash = $hashes[$name];
453 $key = $hash . $dotExt;
454 $dstRel = $repo->getDeletedHashPath( $key ) . $key;
455 $this->deletionBatch[$name] = [ $srcRel, $dstRel ];
459 if ( !$repo->hasSha1Storage() ) {
462 $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch );
463 if ( !$checkStatus->isGood() ) {
464 $status->merge( $checkStatus );
467 $this->deletionBatch = $checkStatus->value;
470 $status = $this->file->repo->deleteBatch( $this->deletionBatch );
471 if ( !$status->isGood() ) {
472 $status->merge( $status );
476 if ( !$status->isOK() ) {
481 $dbw = $this->file->repo->getPrimaryDB();
483 $dbw->startAtomic( __METHOD__ );
486 $this->doDBInserts();
488 $this->doDBDeletes();
492 $dbw->endAtomic( __METHOD__ );
495 ScopedCallback::consume( $unlockScope );
508 foreach ( $batch as [ $src, ] ) {
509 $files[$src] = $this->file->repo->getVirtualUrl(
'public' ) .
'/' . rawurlencode( $src );
512 $result = $this->file->repo->fileExistsBatch( $files );
513 if ( in_array(
null, $result,
true ) ) {
514 return Status::newFatal(
'backend-fail-internal',
515 $this->file->repo->getBackend()->getName() );
519 foreach ( $batch as $batchItem ) {
520 if ( $result[$batchItem[0]] ) {
521 $newBatch[] = $batchItem;
525 return Status::newGood( $newBatch );