93 $dbw = $this->file->repo->getPrimaryDB();
94 $result = $dbw->newSelectQueryBuilder()
95 ->select( [
'oi_archive_name' ] )
97 ->where( [
'oi_name' => $this->file->getName() ] )
98 ->caller( __METHOD__ )->fetchResultSet();
100 foreach ( $result as $row ) {
101 $this->
addOld( $row->oi_archive_name );
102 $archiveNames[] = $row->oi_archive_name;
105 return $archiveNames;
130 [ $oldRels, $deleteCurrent ] = $this->
getOldRels();
132 if ( $deleteCurrent ) {
133 $hashes[
'.'] = $this->file->getSha1();
136 if ( count( $oldRels ) ) {
137 $dbw = $this->file->repo->getPrimaryDB();
138 $res = $dbw->newSelectQueryBuilder()
139 ->select( [
'oi_archive_name',
'oi_sha1' ] )
142 'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) ),
143 'oi_name' => $this->file->getName()
145 ->caller( __METHOD__ )->fetchResultSet();
147 foreach ( $res as $row ) {
148 if ( $row->oi_archive_name ===
'' ) {
150 $hashes[$row->oi_archive_name] =
false;
153 if ( rtrim( $row->oi_sha1,
"\0" ) ===
'' ) {
155 $oldUrl = $this->file->getArchiveVirtualUrl( $row->oi_archive_name );
156 $props = $this->file->repo->getFileProps( $oldUrl );
158 if ( $props[
'fileExists'] ) {
160 $dbw->newUpdateQueryBuilder()
161 ->update(
'oldimage' )
162 ->set( [
'oi_sha1' => $props[
'sha1'] ] )
164 'oi_name' => $this->file->getName(),
165 'oi_archive_name' => $row->oi_archive_name,
167 ->caller( __METHOD__ )->execute();
168 $hashes[$row->oi_archive_name] = $props[
'sha1'];
170 $hashes[$row->oi_archive_name] =
false;
173 $hashes[$row->oi_archive_name] = $row->oi_sha1;
178 $missing = array_diff_key( $this->srcRels, $hashes );
180 foreach ( $missing as $name => $rel ) {
181 $status->
error(
'filedelete-old-unregistered', $name );
184 foreach ( $hashes as $name => $hash ) {
186 $status->
error(
'filedelete-missing', $this->srcRels[$name] );
187 unset( $hashes[$name] );
196 $dbw = $this->file->repo->getPrimaryDB();
198 $commentStore = MediaWikiServices::getInstance()->getCommentStore();
200 $encTimestamp = $dbw->addQuotes( $dbw->timestamp( $now ) );
201 $encUserId = $dbw->addQuotes( $this->user->getId() );
202 $encGroup = $dbw->addQuotes(
'deleted' );
203 $ext = $this->file->getExtension();
204 $dotExt = $ext ===
'' ?
'' :
".$ext";
205 $encExt = $dbw->addQuotes( $dotExt );
206 [ $oldRels, $deleteCurrent ] = $this->getOldRels();
209 if ( $this->suppress ) {
210 $bitfield = RevisionRecord::SUPPRESSED_ALL;
212 $bitfield =
'oi_deleted';
215 if ( $deleteCurrent ) {
216 $tables = [
'image' ];
218 'fa_storage_group' => $encGroup,
219 'fa_storage_key' => $dbw->conditional(
220 [
'img_sha1' =>
'' ],
221 $dbw->addQuotes(
'' ),
222 $dbw->buildConcat( [
"img_sha1", $encExt ] )
224 'fa_deleted_user' => $encUserId,
225 'fa_deleted_timestamp' => $encTimestamp,
226 'fa_deleted' => $this->suppress ? $bitfield : 0,
227 'fa_name' =>
'img_name',
228 'fa_archive_name' =>
'NULL',
229 'fa_size' =>
'img_size',
230 'fa_width' =>
'img_width',
231 'fa_height' =>
'img_height',
232 'fa_metadata' =>
'img_metadata',
233 'fa_bits' =>
'img_bits',
234 'fa_media_type' =>
'img_media_type',
235 'fa_major_mime' =>
'img_major_mime',
236 'fa_minor_mime' =>
'img_minor_mime',
237 'fa_description_id' =>
'img_description_id',
238 'fa_timestamp' =>
'img_timestamp',
239 'fa_sha1' =>
'img_sha1',
240 'fa_actor' =>
'img_actor',
244 $fields += array_map(
245 [ $dbw,
'addQuotes' ],
246 $commentStore->insert( $dbw,
'fa_deleted_reason', $this->reason )
249 $dbw->insertSelect(
'filearchive', $tables, $fields,
250 [
'img_name' => $this->file->getName() ], __METHOD__, [
'IGNORE' ], [], $joins );
253 if ( count( $oldRels ) ) {
254 $queryBuilder = FileSelectQueryBuilder::newForOldFile( $dbw );
257 ->where( [
'oi_name' => $this->file->getName() ] )
258 ->andWhere( [
'oi_archive_name' => array_map(
'strval', array_keys( $oldRels ) ) ] );
259 $res = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
261 if ( $res->numRows() ) {
262 $reason = $commentStore->createComment( $dbw, $this->reason );
263 foreach ( $res as $row ) {
264 $comment = $commentStore->getComment(
'oi_description', $row );
267 'fa_storage_group' =>
'deleted',
268 'fa_storage_key' => ( $row->oi_sha1 ===
'' )
270 :
"{$row->oi_sha1}{$dotExt}",
271 'fa_deleted_user' => $this->user->getId(),
272 'fa_deleted_timestamp' => $dbw->timestamp( $now ),
274 'fa_deleted' => $this->suppress ? $bitfield : $row->oi_deleted,
275 'fa_name' => $row->oi_name,
276 'fa_archive_name' => $row->oi_archive_name,
277 'fa_size' => $row->oi_size,
278 'fa_width' => $row->oi_width,
279 'fa_height' => $row->oi_height,
280 'fa_metadata' => $row->oi_metadata,
281 'fa_bits' => $row->oi_bits,
282 'fa_media_type' => $row->oi_media_type,
283 'fa_major_mime' => $row->oi_major_mime,
284 'fa_minor_mime' => $row->oi_minor_mime,
285 'fa_actor' => $row->oi_actor,
286 'fa_timestamp' => $row->oi_timestamp,
287 'fa_sha1' => $row->oi_sha1
288 ] + $commentStore->insert( $dbw,
'fa_deleted_reason', $reason )
289 + $commentStore->insert( $dbw,
'fa_description', $comment );
293 $dbw->newInsertQueryBuilder()
294 ->insertInto(
'filearchive' )
296 ->rows( $rowsInsert )
297 ->caller( __METHOD__ )->execute();
328 $repo = $this->file->getRepo();
329 $lockStatus = $this->file->acquireFileLock();
330 if ( !$lockStatus->isOK() ) {
333 $unlockScope =
new ScopedCallback(
function () {
334 $this->file->releaseFileLock();
337 $status = $this->file->repo->
newGood();
339 $hashes = $this->getHashes( $status );
340 $this->deletionBatch = [];
341 $ext = $this->file->getExtension();
342 $dotExt = $ext ===
'' ?
'' :
".$ext";
344 foreach ( $this->srcRels as $name => $srcRel ) {
346 if ( isset( $hashes[$name] ) ) {
347 $hash = $hashes[$name];
348 $key = $hash . $dotExt;
349 $dstRel = $repo->getDeletedHashPath( $key ) . $key;
350 $this->deletionBatch[$name] = [ $srcRel, $dstRel ];
354 if ( !$repo->hasSha1Storage() ) {
357 $checkStatus = $this->removeNonexistentFiles( $this->deletionBatch );
358 if ( !$checkStatus->isGood() ) {
359 $status->merge( $checkStatus );
362 $this->deletionBatch = $checkStatus->value;
365 $status = $this->file->repo->deleteBatch( $this->deletionBatch );
366 if ( !$status->isGood() ) {
367 $status->merge( $status );
371 if ( !$status->isOK() ) {
376 $dbw = $this->file->repo->getPrimaryDB();
378 $dbw->startAtomic( __METHOD__ );
381 $this->doDBInserts();
383 $this->doDBDeletes();
387 $dbw->endAtomic( __METHOD__ );
390 ScopedCallback::consume( $unlockScope );
403 foreach ( $batch as [ $src, ] ) {
404 $files[$src] = $this->file->repo->getVirtualUrl(
'public' ) .
'/' . rawurlencode( $src );
407 $result = $this->file->repo->fileExistsBatch( $files );
408 if ( in_array(
null, $result,
true ) ) {
409 return Status::newFatal(
'backend-fail-internal',
410 $this->file->repo->getBackend()->getName() );
414 foreach ( $batch as $batchItem ) {
415 if ( $result[$batchItem[0]] ) {
416 $newBatch[] = $batchItem;
420 return Status::newGood( $newBatch );