/** * Creates a commit. * * Uses a temporary file to construct the commit message because on Windows, multi-line * commit message cannot be created on CLI and it's generally a more flexible solution * (very long commit messages, etc.). * * @param CommitMessage|string $message * @param string $authorName * @param string $authorEmail */ public function commit($message, $authorName, $authorEmail) { if (is_string($message)) { $commitMessage = $message; $body = null; } else { $subject = $message->getSubject(); $body = $message->getBody(); $commitMessage = $this->commitMessagePrefix . $subject; } if ($body != null) { $commitMessage .= "\n\n" . $body; } $tempCommitMessageFilename = md5(rand()); $tempCommitMessagePath = $this->tempDirectory . '/' . $tempCommitMessageFilename; file_put_contents($tempCommitMessagePath, $commitMessage); // Unfortunatelly, `git commit --author=...` is not enough. // It doesn't work with empty both local and global config. $localConfigUserName = $this->runShellCommandWithStandardOutput('git config --local user.name'); $localConfigUserEmail = $this->runShellCommandWithStandardOutput('git config --local user.email'); $this->runShellCommand('git config --local user.name %s', $authorName); $this->runShellCommand('git config --local user.email %s', $authorEmail); $this->runShellCommand("git commit --file=%s", $tempCommitMessagePath); FileSystem::remove($tempCommitMessagePath); if ($localConfigUserName === null) { $this->runShellCommand('git config --local --unset user.name'); } else { $this->runShellCommand('git config --local user.name %s', $localConfigUserName); } if ($localConfigUserEmail === null) { $this->runShellCommand('git config --local --unset user.email'); } else { $this->runShellCommand('git config --local user.email %s', $localConfigUserEmail); } }
public function delete($restriction) { $fileName = $this->getEntityFilename($restriction[$this->entityInfo->vpidColumnName]); if (is_file($fileName)) { $entity = $this->loadEntity($restriction[$this->entityInfo->vpidColumnName]); FileSystem::remove($fileName); return $this->createChangeInfo($entity, $entity, 'delete'); } else { return null; } }
/** * Most of the actual deactivation work is done here. Called either as a response * to the user confirming the deactivation on `?page=versionpress/admin/deactivate.php` * or is called directly from vp_deactivate() if the confirmation screen was not necessary. */ function vp_admin_post_confirm_deactivation() { define('VP_DEACTIVATING', true); if (WpdbReplacer::isReplaced()) { WpdbReplacer::restoreOriginal(); } if (file_exists(VERSIONPRESS_ACTIVATION_FILE)) { FileSystem::remove(VERSIONPRESS_ACTIVATION_FILE); } FileSystem::remove(VERSIONPRESS_MIRRORING_DIR); global $versionPressContainer; /** @var Committer $committer */ $committer = $versionPressContainer->resolve(VersionPressServices::COMMITTER); $committer->forceChangeInfo(new VersionPressChangeInfo("deactivate")); /** @var WpdbMirrorBridge $wpdbMirrorBridge */ $wpdbMirrorBridge = $versionPressContainer->resolve(VersionPressServices::WPDB_MIRROR_BRIDGE); $wpdbMirrorBridge->disable(); global $wpdb; $table_prefix = $wpdb->prefix; $queries[] = "DROP TABLE IF EXISTS `{$table_prefix}vp_id`"; $vpOptionsReflection = new ReflectionClass('VersionPress\\Initialization\\VersionPressOptions'); $usermetaToDelete = array_values($vpOptionsReflection->getConstants()); $queryRestriction = '"' . join('", "', $usermetaToDelete) . '"'; $queries[] = "DELETE FROM `{$table_prefix}usermeta` WHERE meta_key IN ({$queryRestriction})"; foreach ($queries as $query) { $wpdb->query($query); } delete_option('vp_rest_api_plugin_version'); deactivate_plugins("versionpress/versionpress.php", true); if (defined('WP_ADMIN')) { wp_redirect(admin_url("plugins.php")); } }
<?php /** * Uninstallation script for VersionPress. Most things already happened in the * `vp_admin_post_confirm_deactivation` hook; here, we just move the .git repo. * * Testing tip: place exit() at the end of the script and then in the browser * just go back and try again. * * @see vp_admin_post_confirm_deactivation() */ use VersionPress\Utils\FileSystem; use VersionPress\Utils\SecurityUtils; use VersionPress\Utils\UninstallationUtil; defined('WP_UNINSTALL_PLUGIN') or die('Direct access not allowed'); require_once dirname(__FILE__) . '/bootstrap.php'; if (UninstallationUtil::uninstallationShouldRemoveGitRepo()) { $backupsDir = WP_CONTENT_DIR . '/vpbackups'; if (!file_exists($backupsDir)) { FileSystem::mkdir($backupsDir); file_put_contents($backupsDir . '/.gitignore', 'git-backup-*'); SecurityUtils::protectDirectory($backupsDir); } $backupPath = $backupsDir . '/git-backup-' . date("YmdHis"); FileSystem::rename(ABSPATH . '.git', $backupPath, true); $productionGitignore = ABSPATH . '.gitignore'; $templateGitignore = __DIR__ . '/src/Initialization/.gitignore.tpl'; if (FileSystem::filesHaveSameContents($productionGitignore, $templateGitignore)) { FileSystem::remove($productionGitignore); } }
private static function getPermissionInfo() { $proc = proc_open('whoami', [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes); $procOpenUser = trim(stream_get_contents($pipes[1])); $processInfo = ['exec-user' => exec('whoami'), 'proc_open-user' => $procOpenUser]; $writeTargets = ['ABSPATH' => ABSPATH, 'WP_CONTENT_DIR' => WP_CONTENT_DIR, 'sys_temp_dir' => sys_get_temp_dir()]; foreach ($writeTargets as $target => $directory) { $filePath = $directory . '/' . '.vp-try-write-php'; /** @noinspection PhpUsageOfSilenceOperatorInspection */ @file_put_contents($filePath, ""); $processInfo['php-can-write'][$target] = is_file($filePath); FileSystem::remove($filePath); $processInfo['php-can-delete'][$target] = !is_file($filePath); $filePath = $directory . '/' . '.vp-try-write-process'; $process = new Process(sprintf("echo test > %s", ProcessUtils::escapeshellarg($filePath))); $process->run(); $processInfo['process-can-write'][$target] = is_file($filePath); try { FileSystem::remove($filePath); $processInfo['php-can-delete-file-created-by-process'][$target] = !is_file($filePath); } catch (IOException $ex) { $processInfo['php-can-delete-file-created-by-process'][$target] = false; } } return $processInfo; }
public static function tearDownAfterClass() { parent::tearDownAfterClass(); FileSystem::remove(self::$repositoryPath); FileSystem::remove(self::$tempPath); }
/** * Checks if there is any change in the `$mirror` and commits it. If there was a forced * change set, it takes precedence. */ public function commit() { if ($this->commitDisabled) { return; } if (count($this->forcedChangeInfos) > 0) { $changeInfoList = $this->forcedChangeInfos; } elseif ($this->shouldCommit()) { $changeInfoList = array_merge($this->postponedChangeInfos, $this->mirror->getChangeList()); if (empty($changeInfoList)) { return; } } else { return; } if ($this->commitPostponed) { $this->postponeChangeInfo($changeInfoList); $this->commitPostponed = false; $this->postponeKey = null; $this->flushChangeLists(); return; } if (is_user_logged_in() && is_admin()) { $currentUser = wp_get_current_user(); /** @noinspection PhpUndefinedFieldInspection */ $authorName = $currentUser->display_name; /** @noinspection PhpUndefinedFieldInspection */ $authorEmail = $currentUser->user_email; } else { if (defined('WP_CLI') && WP_CLI) { $authorName = GitConfig::$wpcliUserName; $authorEmail = GitConfig::$wpcliUserEmail; } else { $authorName = "Non-admin action"; $authorEmail = "*****@*****.**"; } } $changeInfoLists = $this->preprocessChangeInfoList($changeInfoList); $mutex = new Mutex(VERSIONPRESS_TEMP_DIR, 'committer-stage-commit'); $mutex->lock(); if (count($this->forcedChangeInfos) === 1) { // If there is one forced change info, we can commit all changes made by change info objects emitted from // storages. If there will be more forced change info objects in the future, we have to come up with // something smarter. For now, it solves WP-430. $this->stageRelatedFiles(new ChangeInfoEnvelope($this->mirror->getChangeList())); } foreach ($changeInfoLists as $listToCommit) { $changeInfoEnvelope = new ChangeInfoEnvelope($listToCommit); $this->stageRelatedFiles($changeInfoEnvelope); $this->repository->commit($changeInfoEnvelope->getCommitMessage(), $authorName, $authorEmail); } $mutex->release(); if (count($this->forcedChangeInfos) > 0 && $this->forcedChangeInfos[0]->getScope() === 'wordpress') { FileSystem::remove(ABSPATH . 'versionpress.maintenance'); } $this->flushChangeLists(); }
/** * Ensures that the clean installation of WordPress is available locally. If not, * downloads it from wp.org and stores it as `<clean-installations-dir>/<version>`. */ private function ensureCleanInstallationIsAvailable() { $cleanInstallationPath = $this->getCleanInstallationPath(); if (!$this->isCorrectlyDownloaded($cleanInstallationPath)) { FileSystem::remove($cleanInstallationPath); FileSystem::mkdir($cleanInstallationPath); $wpVersion = $this->siteConfig->wpVersion; $wpLocale = $this->siteConfig->wpLocale; $downloadCommand = "wp core download --path=\"{$cleanInstallationPath}\" --version=\"{$wpVersion}\""; if ($wpLocale) { $downloadCommand .= " --locale={$wpLocale}"; } $this->exec($downloadCommand, null); } }
private function tryWrite() { $filename = ".vp-try-write"; $testPaths = [ABSPATH, WP_CONTENT_DIR, sys_get_temp_dir()]; $writable = true; foreach ($testPaths as $directory) { $filePath = $directory . '/' . $filename; /** @noinspection PhpUsageOfSilenceOperatorInspection */ @file_put_contents($filePath, ""); $writable &= is_file($filePath); FileSystem::remove($filePath); // Trying to create file from process (issue #522) $process = new Process(sprintf("echo test > %s", ProcessUtils::escapeshellarg($filePath))); $process->run(); $writable &= is_file($filePath); try { FileSystem::remove($filePath); } catch (IOException $ex) { $writable = false; // the file could not be deleted - the permissions are wrong } } return $writable; }
/** * Saves all eligible entities into the file system storage (the 'db' folder) */ private function saveDatabaseToStorages() { if (is_dir(VP_VPDB_DIR)) { FileSystem::remove(VP_VPDB_DIR); } FileSystem::mkdir(VP_VPDB_DIR); $entityNames = $this->synchronizerFactory->getSynchronizationSequence(); foreach ($entityNames as $entityName) { $this->createVpidsForEntitiesOfType($entityName); $this->saveEntitiesOfTypeToStorage($entityName); } $mnReferenceDetails = $this->dbSchema->getAllMnReferences(); foreach ($mnReferenceDetails as $referenceDetail) { $this->saveMnReferences($referenceDetail); } }
/** * Saves all eligible entities into the file system storage (the 'db' folder) */ private function saveDatabaseToStorages() { if (is_dir(VERSIONPRESS_MIRRORING_DIR)) { FileSystem::remove(VERSIONPRESS_MIRRORING_DIR); } FileSystem::mkdir(VERSIONPRESS_MIRRORING_DIR); $entityNames = $this->synchronizerFactory->getSynchronizationSequence(); foreach ($entityNames as $entityName) { $this->createVpidsForEntitiesOfType($entityName); $this->saveEntitiesOfTypeToStorage($entityName); $this->reportProgressChange("All " . $entityName . " saved into files"); } }
function vp_disable_maintenance() { FileSystem::remove(ABSPATH . '.maintenance'); }
public static function tearDownAfterClass() { FileSystem::remove(self::$repositoryDir); }
public static function destroyRepository() { FileSystem::remove(self::$repositoryDir); }
/** * Most of the actual deactivation work is done here. Called either as a response * to the user confirming the deactivation on `?page=versionpress/admin/deactivate.php` * or is called directly from vp_deactivate() if the confirmation screen was not necessary. */ function vp_admin_post_confirm_deactivation() { //nonce verification is performed according to 'deactivate-plugin_versionpress/versionpress.php' // as a standard deactivation token for which nonce is generated if (!defined('WP_CLI')) { vp_verify_nonce('deactivate-plugin_versionpress/versionpress.php'); vp_check_permissions(); } define('VP_DEACTIVATING', true); if (WpdbReplacer::isReplaced()) { WpdbReplacer::restoreOriginal(); } if (file_exists(VERSIONPRESS_ACTIVATION_FILE)) { FileSystem::remove(VERSIONPRESS_ACTIVATION_FILE); } $filesChangedByDeactivation = [["type" => "path", "path" => VP_VPDB_DIR . "/*"], ["type" => "path", "path" => ABSPATH . WPINC . "/wp-db.php"], ["type" => "path", "path" => ABSPATH . WPINC . "/wp-db.php.original"], ["type" => "path", "path" => ABSPATH . "/.gitattributes"]]; vp_force_action('versionpress', 'deactivate', null, [], $filesChangedByDeactivation); MergeDriverInstaller::uninstallMergeDriver(VP_PROJECT_ROOT, VERSIONPRESS_PLUGIN_DIR, VP_VPDB_DIR); deactivate_plugins("versionpress/versionpress.php", true); if (defined('WP_ADMIN')) { wp_safe_redirect(admin_url("plugins.php")); exit; } }
protected function tearDown() { parent::tearDown(); FileSystem::remove(__DIR__ . '/entities'); }
private function clean($bugReportDir, $zipFile) { FileSystem::remove($bugReportDir); FileSystem::remove($zipFile); }
/** * Removes everything created by VP, leaves site fresh for new testing. * * ## DETAILS * * Basically does plugin deactivation, removing the Git repo and plugin activation. * Deactivation does things like removing `vpdb`, `db.php`, VersionPress db tables etc. * * @subcommand start-over */ public function startOver($args, $assoc_args) { vp_admin_post_confirm_deactivation(); FileSystem::remove(ABSPATH . '.git'); activate_plugin('versionpress/versionpress.php'); }