protected function purgeFromArchiveTable(LocalFile $file) { $db = $file->getRepo()->getSlaveDB(); $res = $db->select('filearchive', array('fa_archive_name'), array('fa_name' => $file->getName()), __METHOD__); foreach ($res as $row) { $file->purgeOldThumbnails($row->fa_archive_name); } }
/** * Gets titles given file could be moved from * * This will allow us (to try) to get original image and move it to the proper destination path * * @param LocalFile $file * @return Title[] array of titles */ private function getCandidates($file) { $titles = []; // select page_title from redirect join page on page_id = rd_from where rd_namespace = 6 AND rd_title = "PRO_006_Breaker.png"; $res = $this->dbr->select(['redirect', 'page'], 'page_title', ['rd_namespace' => NS_FILE, 'rd_title' => $file->getName()], __METHOD__, [], ['page' => ['JOIN', 'page_id = rd_from']]); while ($row = $res->fetchRow()) { $titles[] = Title::newFromText($row['page_title'], NS_FILE); } return $titles; }
/** * Generate triplets for FileRepo::storeBatch(). * @return array */ function getMoveTriplets() { $moves = array_merge(array($this->cur), $this->olds); $triplets = array(); // The format is: (srcUrl, destZone, destUrl) foreach ($moves as $move) { // $move: (oldRelativePath, newRelativePath) $srcUrl = $this->file->repo->getVirtualUrl() . '/public/' . rawurlencode($move[0]); $triplets[] = array($srcUrl, 'public', $move[1]); wfDebugLog('imagemove', "Generated move triplet for {$this->file->getName()}: {$srcUrl} :: public :: {$move[1]}"); } return $triplets; }
public function saveSettings($settings, $cityId = null) { global $wgCityId, $wgUser; $cityId = empty($cityId) ? $wgCityId : $cityId; // Verify wordmark length ( CONN-116 ) if (!empty($settings['wordmark-text'])) { $settings['wordmark-text'] = trim($settings['wordmark-text']); } if (empty($settings['wordmark-text'])) { // Do not save wordmark if its empty. unset($settings['wordmark-text']); } else { if (mb_strlen($settings['wordmark-text']) > 50) { $settings['wordmark-text'] = mb_substr($settings['wordmark-text'], 0, 50); } } if (isset($settings['favicon-image-name']) && strpos($settings['favicon-image-name'], 'Temp_file_') === 0) { $temp_file = new LocalFile(Title::newFromText($settings['favicon-image-name'], 6), RepoGroup::singleton()->getLocalRepo()); $file = new LocalFile(Title::newFromText(self::FaviconImageName, 6), RepoGroup::singleton()->getLocalRepo()); $file->upload($temp_file->getPath(), '', ''); $temp_file->delete(''); Wikia::invalidateFavicon(); $settings['favicon-image-url'] = $file->getURL(); $settings['favicon-image-name'] = $file->getName(); $file->repo->forceMaster(); $history = $file->getHistory(1); if (count($history) == 1) { $oldFaviconFile = array('url' => $history[0]->getURL(), 'name' => $history[0]->getArchiveName()); } } if (isset($settings['wordmark-image-name']) && strpos($settings['wordmark-image-name'], 'Temp_file_') === 0) { $temp_file = new LocalFile(Title::newFromText($settings['wordmark-image-name'], 6), RepoGroup::singleton()->getLocalRepo()); $file = new LocalFile(Title::newFromText(self::WordmarkImageName, 6), RepoGroup::singleton()->getLocalRepo()); $file->upload($temp_file->getPath(), '', ''); $temp_file->delete(''); $settings['wordmark-image-url'] = $file->getURL(); $settings['wordmark-image-name'] = $file->getName(); $file->repo->forceMaster(); $history = $file->getHistory(1); if (count($history) == 1) { $oldFile = array('url' => $history[0]->getURL(), 'name' => $history[0]->getArchiveName()); } } if (isset($settings['background-image-name']) && strpos($settings['background-image-name'], 'Temp_file_') === 0) { $temp_file = new LocalFile(Title::newFromText($settings['background-image-name'], 6), RepoGroup::singleton()->getLocalRepo()); $file = new LocalFile(Title::newFromText(self::BackgroundImageName, 6), RepoGroup::singleton()->getLocalRepo()); $file->upload($temp_file->getPath(), '', ''); $temp_file->delete(''); $settings['background-image'] = $file->getURL(); $settings['background-image-name'] = $file->getName(); $settings['background-image-width'] = $file->getWidth(); $settings['background-image-height'] = $file->getHeight(); $imageServing = new ImageServing(null, 120, array("w" => "120", "h" => "65")); $settings['user-background-image'] = $file->getURL(); $settings['user-background-image-thumb'] = wfReplaceImageServer($file->getThumbUrl($imageServing->getCut($file->getWidth(), $file->getHeight(), "origin") . "-" . $file->getName())); $file->repo->forceMaster(); $history = $file->getHistory(1); if (count($history) == 1) { $oldBackgroundFile = array('url' => $history[0]->getURL(), 'name' => $history[0]->getArchiveName()); } } $reason = wfMsg('themedesigner-reason', $wgUser->getName()); // update history if (!empty($GLOBALS[self::WikiFactoryHistory])) { $history = $GLOBALS[self::WikiFactoryHistory]; $lastItem = end($history); $revisionId = intval($lastItem['revision']) + 1; } else { $history = array(); $revisionId = 1; } // #140758 - Jakub // validation // default color values foreach (ThemeDesignerHelper::getColorVars() as $sColorVar => $sDefaultValue) { if (!isset($settings[$sColorVar]) || !ThemeDesignerHelper::isValidColor($settings[$sColorVar])) { $settings[$sColorVar] = $sDefaultValue; } } // update WF variable with current theme settings WikiFactory::setVarByName(self::WikiFactorySettings, $cityId, $settings, $reason); // add entry $history[] = array('settings' => $settings, 'author' => $wgUser->getName(), 'timestamp' => wfTimestampNow(), 'revision' => $revisionId); // limit history size to last 10 changes $history = array_slice($history, -self::HistoryItemsLimit); if (count($history) > 1) { for ($i = 0; $i < count($history) - 1; $i++) { if (isset($oldFaviconFile) && isset($history[$i]['settings']['favicon-image-name'])) { if ($history[$i]['settings']['favicon-image-name'] == self::FaviconImageName) { $history[$i]['settings']['favicon-image-name'] = $oldFaviconFile['name']; $history[$i]['settings']['favicon-image-url'] = $oldFaviconFile['url']; } } if (isset($oldFile) && isset($history[$i]['settings']['wordmark-image-name'])) { if ($history[$i]['settings']['wordmark-image-name'] == self::WordmarkImageName) { $history[$i]['settings']['wordmark-image-name'] = $oldFile['name']; $history[$i]['settings']['wordmark-image-url'] = $oldFile['url']; } } if (isset($oldBackgroundFile) && isset($history[$i]['settings']['background-image-name'])) { if ($history[$i]['settings']['background-image-name'] == self::BackgroundImageName) { $history[$i]['settings']['background-image-name'] = $oldBackgroundFile['name']; } } } } WikiFactory::setVarByName(self::WikiFactoryHistory, $cityId, $history, $reason); }
protected function purgeFromArchiveTable(LocalRepo $repo, LocalFile $file) { $dbr = $repo->getSlaveDB(); $res = $dbr->select('filearchive', array('fa_archive_name'), array('fa_name' => $file->getName()), __METHOD__); foreach ($res as $row) { if ($row->fa_archive_name === null) { // Was not an old version (current version names checked already) continue; } $ofile = $repo->newFromArchiveName($file->getTitle(), $row->fa_archive_name); // If there is an orphaned storage file still there...delete it if (!$file->exists() && $repo->fileExists($ofile->getPath())) { $dpath = $this->getDeletedPath($repo, $ofile); if ($repo->fileExists($dpath)) { // Sanity check to avoid data loss $repo->getBackend()->delete(array('src' => $ofile->getPath())); $this->output("Deleted orphan file: {$ofile->getPath()}.\n"); } else { $this->error("File was not deleted: {$ofile->getPath()}.\n"); } } $file->purgeOldThumbnails($row->fa_archive_name); } }
/** * Run the transaction, except the cleanup batch. * The cleanup batch should be run in a separate transaction, because it locks different * rows and there's no need to keep the image row locked while it's acquiring those locks * The caller may have its own transaction open. * So we save the batch and let the caller call cleanup() */ function execute() { global $wgLang; if (!$this->all && !$this->ids) { // Do nothing return $this->file->repo->newGood(); } $exists = $this->file->lock(); $dbw = $this->file->repo->getMasterDB(); $status = $this->file->repo->newGood(); // Fetch all or selected archived revisions for the file, // sorted from the most recent to the oldest. $conditions = array('fa_name' => $this->file->getName()); if (!$this->all) { $conditions[] = 'fa_id IN (' . $dbw->makeList($this->ids) . ')'; } $result = $dbw->select('filearchive', '*', $conditions, __METHOD__, array('ORDER BY' => 'fa_timestamp DESC')); $idsPresent = array(); $storeBatch = array(); $insertBatch = array(); $insertCurrent = false; $deleteIds = array(); $first = true; $archiveNames = array(); foreach ($result as $row) { $idsPresent[] = $row->fa_id; if ($row->fa_name != $this->file->getName()) { $status->error('undelete-filename-mismatch', $wgLang->timeanddate($row->fa_timestamp)); $status->failCount++; continue; } if ($row->fa_storage_key == '') { // Revision was missing pre-deletion $status->error('undelete-bad-store-key', $wgLang->timeanddate($row->fa_timestamp)); $status->failCount++; continue; } $deletedRel = $this->file->repo->getDeletedHashPath($row->fa_storage_key) . $row->fa_storage_key; $deletedUrl = $this->file->repo->getVirtualUrl() . '/deleted/' . $deletedRel; $sha1 = substr($row->fa_storage_key, 0, strcspn($row->fa_storage_key, '.')); # Fix leading zero if (strlen($sha1) == 32 && $sha1[0] == '0') { $sha1 = substr($sha1, 1); } if (is_null($row->fa_major_mime) || $row->fa_major_mime == 'unknown' || is_null($row->fa_minor_mime) || $row->fa_minor_mime == 'unknown' || is_null($row->fa_media_type) || $row->fa_media_type == 'UNKNOWN' || is_null($row->fa_metadata)) { // Refresh our metadata // Required for a new current revision; nice for older ones too. :) $props = RepoGroup::singleton()->getFileProps($deletedUrl); } else { $props = array('minor_mime' => $row->fa_minor_mime, 'major_mime' => $row->fa_major_mime, 'media_type' => $row->fa_media_type, 'metadata' => $row->fa_metadata); } if ($first && !$exists) { // This revision will be published as the new current version $destRel = $this->file->getRel(); $insertCurrent = array('img_name' => $row->fa_name, 'img_size' => $row->fa_size, 'img_width' => $row->fa_width, 'img_height' => $row->fa_height, 'img_metadata' => $props['metadata'], 'img_bits' => $row->fa_bits, 'img_media_type' => $props['media_type'], 'img_major_mime' => $props['major_mime'], 'img_minor_mime' => $props['minor_mime'], 'img_description' => $row->fa_description, 'img_user' => $row->fa_user, 'img_user_text' => $row->fa_user_text, 'img_timestamp' => $row->fa_timestamp, 'img_sha1' => $sha1); // The live (current) version cannot be hidden! if (!$this->unsuppress && $row->fa_deleted) { $storeBatch[] = array($deletedUrl, 'public', $destRel); $this->cleanupBatch[] = $row->fa_storage_key; } } else { $archiveName = $row->fa_archive_name; if ($archiveName == '') { // This was originally a current version; we // have to devise a new archive name for it. // Format is <timestamp of archiving>!<name> $timestamp = wfTimestamp(TS_UNIX, $row->fa_deleted_timestamp); do { $archiveName = wfTimestamp(TS_MW, $timestamp) . '!' . $row->fa_name; $timestamp++; } while (isset($archiveNames[$archiveName])); } $archiveNames[$archiveName] = true; $destRel = $this->file->getArchiveRel($archiveName); $insertBatch[] = array('oi_name' => $row->fa_name, 'oi_archive_name' => $archiveName, 'oi_size' => $row->fa_size, 'oi_width' => $row->fa_width, 'oi_height' => $row->fa_height, 'oi_bits' => $row->fa_bits, 'oi_description' => $row->fa_description, 'oi_user' => $row->fa_user, 'oi_user_text' => $row->fa_user_text, 'oi_timestamp' => $row->fa_timestamp, 'oi_metadata' => $props['metadata'], 'oi_media_type' => $props['media_type'], 'oi_major_mime' => $props['major_mime'], 'oi_minor_mime' => $props['minor_mime'], 'oi_deleted' => $this->unsuppress ? 0 : $row->fa_deleted, 'oi_sha1' => $sha1); } $deleteIds[] = $row->fa_id; if (!$this->unsuppress && $row->fa_deleted & File::DELETED_FILE) { // private files can stay where they are $status->successCount++; } else { $storeBatch[] = array($deletedUrl, 'public', $destRel); $this->cleanupBatch[] = $row->fa_storage_key; } $first = false; } unset($result); // Add a warning to the status object for missing IDs $missingIds = array_diff($this->ids, $idsPresent); foreach ($missingIds as $id) { $status->error('undelete-missing-filearchive', $id); } // Remove missing files from batch, so we don't get errors when undeleting them $storeBatch = $this->removeNonexistentFiles($storeBatch); // Run the store batch // Use the OVERWRITE_SAME flag to smooth over a common error $storeStatus = $this->file->repo->storeBatch($storeBatch, FileRepo::OVERWRITE_SAME); $status->merge($storeStatus); if (!$status->isGood()) { // Even if some files could be copied, fail entirely as that is the // easiest thing to do without data loss $this->cleanupFailedBatch($storeStatus, $storeBatch); $status->ok = false; $this->file->unlock(); return $status; } // Run the DB updates // Because we have locked the image row, key conflicts should be rare. // If they do occur, we can roll back the transaction at this time with // no data loss, but leaving unregistered files scattered throughout the // public zone. // This is not ideal, which is why it's important to lock the image row. if ($insertCurrent) { $dbw->insert('image', $insertCurrent, __METHOD__); } if ($insertBatch) { $dbw->insert('oldimage', $insertBatch, __METHOD__); } if ($deleteIds) { $dbw->delete('filearchive', array('fa_id IN (' . $dbw->makeList($deleteIds) . ')'), __METHOD__); } // If store batch is empty (all files are missing), deletion is to be considered successful if ($status->successCount > 0 || !$storeBatch) { if (!$exists) { wfDebug(__METHOD__ . " restored {$status->successCount} items, creating a new current\n"); // Update site_stats $site_stats = $dbw->tableName('site_stats'); $dbw->query("UPDATE {$site_stats} SET ss_images=ss_images+1", __METHOD__); $this->file->purgeEverything(); } else { wfDebug(__METHOD__ . " restored {$status->successCount} as archived versions\n"); $this->file->purgeDescription(); $this->file->purgeHistory(); } } $this->file->unlock(); return $status; }
public function testGetName() { $this->assertEquals('myFile.ext', $this->fixture_file->getName()); $otherFile = new LocalFile(TESTS_FSI_LOCALFILE_TMP_PATH . '/my.File.2.EXT'); $this->assertEquals('my.File.2.EXT', $otherFile->getName()); $this->assertEquals('myDir', $this->fixture_dir->getName()); }
/** * @param LocalFile $file * @param string $url * @param string $comment * @return FileRepoStatus */ private function uploadFromUrl($file, $url, $comment) { $tmpFile = tempnam(wfTempDir(), 'upload'); // fetch an asset $res = Http::get($url, 'default', ['noProxy' => true]); $this->assertTrue($res !== false, 'File from <' . $url . '> should be uploaded'); file_put_contents($tmpFile, $res); $this->assertTrue(is_readable($tmpFile), 'Temp file for HTTP upload should be created and readable'); Wikia::log(__METHOD__, false, sprintf('uploading %s (%.2f kB) as %s', $tmpFile, filesize($tmpFile) / 1024, $file->getName()), true); $res = $file->upload($tmpFile, $comment, ''); #unlink( $tmpFile ); return $res; }
<input id="ImageUploadUseExisting" type="hidden" name="ImageUploadUseExisting" value="" /> <input id="ImageUploadRename" type="hidden" name="ImageUploadRename" value="" /> <input type="hidden" name="type" value="<?php echo isset($file) ? htmlspecialchars($file->media_type) : ''; ?> " /> <input type="hidden" name="ImageIsConflict" value="1" /> <input id="ImageAttribution" type="hidden" name="ImageAttribution" value="<?php echo htmlspecialchars($image_comment); ?> " /> <?php $file_temp = new TempLocalFile(Title::newFromText($mwname, NS_IMAGE), RepoGroup::singleton()->getLocalRepo()); $existing_title = Title::newFromText($name, NS_IMAGE); $file_existing = new LocalFile($existing_title, RepoGroup::singleton()->getLocalRepo()); print wfMsg('eiu-conflict-inf', $file_existing->getName()); ?> <input name="mwname" type="hidden" value="<?php echo htmlspecialchars($mwname); ?> " /> <br/><br/> <table cellspacing="0" class="ImageUploadConflictTable wh_block" width='100%'> <tr> <td> <h2><?php echo wfMsg('eiu-rename'); ?> </h2> </td>
<input id="ImageUploadExtraId" type="hidden" value="<?php echo urlencode($extraId); ?> " /> <?php $file_mwname = new FakeLocalFile(Title::newFromText($mwname, 6), RepoGroup::singleton()->getLocalRepo()); $file_name = new LocalFile(Title::newFromText($partname . '.' . $extension, 6), RepoGroup::singleton()->getLocalRepo()); echo wfMsg('wmu-conflict-inf', $file_name->getName()); ?> <table cellspacing="0" id="ImageUploadConflictTable"> <tr> <td style="border-right: 1px solid #CCC;"> <h2><?php echo wfMsg('wmu-rename'); ?> </h2> <div style="margin: 5px 0;"> <input type="text" id="ImageUploadRenameName" value="<?php echo $partname; ?> " /> <label for="ImageUploadRenameName">.<?php echo $extension; ?> </label> <input id="ImageUploadRenameExtension" type="hidden" value="<?php echo $extension; ?> " /> <input type="button" value="<?php echo wfMsg('wmu-insert');