eraseArchivedFile.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. /**
  3. * Delete archived (non-current) files from storage
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. * @ingroup Maintenance
  22. * @author Aaron Schulz
  23. */
  24. require_once __DIR__ . '/Maintenance.php';
  25. /**
  26. * Maintenance script to delete archived (non-current) files from storage.
  27. *
  28. * @todo Maybe add some simple logging
  29. *
  30. * @ingroup Maintenance
  31. * @since 1.22
  32. */
  33. class EraseArchivedFile extends Maintenance {
  34. public function __construct() {
  35. parent::__construct();
  36. $this->addDescription( 'Erases traces of deleted files.' );
  37. $this->addOption( 'delete', 'Perform the deletion' );
  38. $this->addOption( 'filename', 'File name', false, true );
  39. $this->addOption( 'filekey', 'File storage key (with extension) or "*"', true, true );
  40. }
  41. public function execute() {
  42. if ( !$this->hasOption( 'delete' ) ) {
  43. $this->output( "Use --delete to actually confirm this script\n" );
  44. }
  45. $filekey = $this->getOption( 'filekey' );
  46. $filename = $this->getOption( 'filename' );
  47. if ( $filekey === '*' ) { // all versions by name
  48. if ( !strlen( $filename ) ) {
  49. $this->error( "Missing --filename parameter.", 1 );
  50. }
  51. $afile = false;
  52. } else { // specified version
  53. $dbw = $this->getDB( DB_MASTER );
  54. $row = $dbw->selectRow( 'filearchive', '*',
  55. [ 'fa_storage_group' => 'deleted', 'fa_storage_key' => $filekey ],
  56. __METHOD__ );
  57. if ( !$row ) {
  58. $this->error( "No deleted file exists with key '$filekey'.", 1 );
  59. }
  60. $filename = $row->fa_name;
  61. $afile = ArchivedFile::newFromRow( $row );
  62. }
  63. $file = wfLocalFile( $filename );
  64. if ( $file->exists() ) {
  65. $this->error( "File '$filename' is still a public file, use the delete form.\n", 1 );
  66. }
  67. $this->output( "Purging all thumbnails for file '$filename'..." );
  68. $file->purgeCache();
  69. $this->output( "done.\n" );
  70. if ( $afile instanceof ArchivedFile ) {
  71. $this->scrubVersion( $afile );
  72. } else {
  73. $this->output( "Finding deleted versions of file '$filename'...\n" );
  74. $this->scrubAllVersions( $filename );
  75. $this->output( "Done\n" );
  76. }
  77. }
  78. protected function scrubAllVersions( $name ) {
  79. $dbw = $this->getDB( DB_MASTER );
  80. $res = $dbw->select( 'filearchive', '*',
  81. [ 'fa_name' => $name, 'fa_storage_group' => 'deleted' ],
  82. __METHOD__ );
  83. foreach ( $res as $row ) {
  84. $this->scrubVersion( ArchivedFile::newFromRow( $row ) );
  85. }
  86. }
  87. protected function scrubVersion( ArchivedFile $archivedFile ) {
  88. $key = $archivedFile->getStorageKey();
  89. $name = $archivedFile->getName();
  90. $ts = $archivedFile->getTimestamp();
  91. $repo = RepoGroup::singleton()->getLocalRepo();
  92. $path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
  93. if ( $this->hasOption( 'delete' ) ) {
  94. $status = $repo->getBackend()->delete( [ 'src' => $path ] );
  95. if ( $status->isOK() ) {
  96. $this->output( "Deleted version '$key' ($ts) of file '$name'\n" );
  97. } else {
  98. $this->output( "Failed to delete version '$key' ($ts) of file '$name'\n" );
  99. $this->output( print_r( $status->getErrorsArray(), true ) );
  100. }
  101. } else {
  102. $this->output( "Would delete version '{$key}' ({$ts}) of file '$name'\n" );
  103. }
  104. }
  105. }
  106. $maintClass = "EraseArchivedFile";
  107. require_once RUN_MAINTENANCE_IF_MAIN;