/** * Delete a file from the file store. * Caller's responsibility to make sure it's not being used by another row. * * File is not actually removed until transaction commit. * Should be protected by FileStore::lock() to avoid race conditions. * * @param $key storage key string * @throws FSException if file can't be deleted * @return FSTransaction */ function delete($key) { $destPath = $this->filePath($key); if (false === $destPath) { throw new FSExcepton("file store does not contain file '{$key}'"); } else { return FileStore::deleteFile($destPath); } }
/** * Do the dirty work of backing up an image row and its file * (if $wgSaveDeletedFiles is on) and removing the originals. * * Must be run while the file store is locked and a database * transaction is open to avoid race conditions. * * @return FSTransaction */ private function prepareDeleteVersion($path, $reason, $table, $fieldMap, $where, $suppress = false, $fname) { global $wgUser, $wgSaveDeletedFiles; // Dupe the file into the file store if (file_exists($path)) { if ($wgSaveDeletedFiles) { $group = 'deleted'; $store = FileStore::get($group); $key = FileStore::calculateKey($path, $this->extension); $transaction = $store->insert($key, $path, FileStore::DELETE_ORIGINAL); } else { $group = null; $key = null; $transaction = FileStore::deleteFile($path); } } else { wfDebug(__METHOD__ . " deleting already-missing '{$path}'; moving on to database\n"); $group = null; $key = null; $transaction = new FSTransaction(); // empty } if ($transaction === false) { // Fail to restore? wfDebug(__METHOD__ . ": import to file store failed, aborting\n"); throw new MWException("Could not archive and delete file {$path}"); return false; } // Bitfields to further supress the image content // Note that currently, live images are stored elsewhere // and cannot be partially deleted $bitfield = 0; if ($suppress) { $bitfield |= self::DELETED_FILE; $bitfield |= self::DELETED_COMMENT; $bitfield |= self::DELETED_USER; $bitfield |= self::DELETED_RESTRICTED; } $dbw = wfGetDB(DB_MASTER); $storageMap = array('fa_storage_group' => $dbw->addQuotes($group), 'fa_storage_key' => $dbw->addQuotes($key), 'fa_deleted_user' => $dbw->addQuotes($wgUser->getId()), 'fa_deleted_timestamp' => $dbw->timestamp(), 'fa_deleted_reason' => $dbw->addQuotes($reason), 'fa_deleted' => $bitfield); $allFields = array_merge($storageMap, $fieldMap); try { if ($wgSaveDeletedFiles) { $dbw->insertSelect('filearchive', $table, $allFields, $where, $fname); } $dbw->delete($table, $where, $fname); } catch (DBQueryError $e) { // Something went horribly wrong! // Leave the file as it was... wfDebug(__METHOD__ . ": database error, rolling back file transaction\n"); $transaction->rollback(); throw $e; } return $transaction; }
function deletePermanently($title) { global $wgOut; $ns = $title->getNamespace(); $t = $title->getDBkey(); $id = $title->getArticleID(); $cats = $title->getParentCategories(); $dbw = wfGetDB(DB_MASTER); $dbw->begin(); #### ## First delete entries, which are in direct relation with the page: #### # delete redirect... $dbw->delete('redirect', array('rd_from' => $id), __METHOD__); # delete external link... $dbw->delete('externallinks', array('el_from' => $id), __METHOD__); # delete language link... $dbw->delete('langlinks', array('ll_from' => $id), __METHOD__); # delete search index... $dbw->delete('searchindex', array('si_page' => $id), __METHOD__); # Delete restrictions for the page $dbw->delete('page_restrictions', array('pr_page' => $id), __METHOD__); # Delete page Links $dbw->delete('pagelinks', array('pl_from' => $id), __METHOD__); # delete category links $dbw->delete('categorylinks', array('cl_from' => $id), __METHOD__); # delete template links $dbw->delete('templatelinks', array('tl_from' => $id), __METHOD__); # read text entries for all revisions and delete them. $res = $dbw->select('revision', 'rev_text_id', "rev_page={$id}"); while ($row = $dbw->fetchObject($res)) { $value = $row->rev_text_id; $dbw->delete('text', array('old_id' => $value), __METHOD__); } # In the table 'revision' : Delete all the revision of the page where 'rev_page' = $id $dbw->delete('revision', array('rev_page' => $id), __METHOD__); # delete image links $dbw->delete('imagelinks', array('il_from' => $id), __METHOD__); #### ## then delete entries which are not in direct relation with the page: #### # Clean up recentchanges entries... $dbw->delete('recentchanges', array('rc_namespace' => $ns, 'rc_title' => $t), __METHOD__); # read text entries for all archived pages and delete them. $res = $dbw->select('archive', 'ar_text_id', array('ar_namespace' => $ns, 'ar_title' => $t)); while ($row = $dbw->fetchObject($res)) { $value = $row->ar_text_id; $dbw->delete('text', array('old_id' => $value), __METHOD__); } # Clean archive entries... $dbw->delete('archive', array('ar_namespace' => $ns, 'ar_title' => $t), __METHOD__); # Clean up log entries... $dbw->delete('logging', array('log_namespace' => $ns, 'log_title' => $t), __METHOD__); # Clean up watchlist... $dbw->delete('watchlist', array('wl_namespace' => $ns, 'wl_title' => $t), __METHOD__); # In the table 'page' : Delete the page entry $dbw->delete('page', array('page_id' => $id), __METHOD__); #### ## If the article belongs to a category, update category counts #### if (!empty($cats)) { foreach ($cats as $parentcat => $currentarticle) { $catname = split(':', $parentcat, 2); $cat = Category::newFromName($catname[1]); $cat->refreshCounts(); } } #### ## If an image is beeing deleted, some extra work needs to be done #### if ($ns == NS_IMAGE) { $file = wfFindFile($t); if ($file) { # Get all filenames of old versions: $fields = OldLocalFile::selectFields(); $res = $dbw->select('oldimage', $fields, array('oi_name' => $t)); while ($row = $dbw->fetchObject($res)) { $oldLocalFile = OldLocalFile::newFromRow($row, $file->repo); $path = $oldLocalFile->getArchivePath() . '/' . $oldLocalFile->getArchiveName(); try { # Using the FileStore to delete the file $transaction = FileStore::deleteFile($path); $transaction->commit(); } catch (Exception $e) { $wgOut->addHTML($e->getMessage()); } } $path = $file->getPath(); try { # Using the FileStore to delete the file itself $transaction = FileStore::deleteFile($path); $transaction->commit(); } catch (Exception $e) { $wgOut->addHTML($e->getMessage()); } } # clean the filearchive for the given filename: $fa_archive_name = array(); $res = $dbw->select('filearchive', 'fa_storage_key', array('fa_name' => $t)); while ($row = $dbw->fetchObject($res)) { $key = $row->fa_storage_key; # Using the FileStore to delete the file $store = FileStore::get('deleted'); $transaction = $store->delete($key); $transaction->commit(); } # Delete old db entries of the image: $dbw->delete('oldimage', array('oi_name' => $t), __METHOD__); # Delete archive entries of the image: $dbw->delete('filearchive', array('fa_name' => $t), __METHOD__); # Delete image entry: $dbw->delete('image', array('img_name' => $t), __METHOD__); $dbw->commit(); $linkCache = LinkCache::singleton(); $linkCache->clear(); } }