public function prepare_activateTwoPlugins() { $plugin1Path = PathUtils::getRelativePath(self::$testConfig->testSite->path, self::$pluginInfo['zipfile']); $plugin2Path = PathUtils::getRelativePath(self::$testConfig->testSite->path, self::$secondPluginInfo['zipfile']); self::$wpAutomation->runWpCliCommand('plugin', 'install', [$plugin1Path, $plugin2Path]); $this->url(self::$wpAdminPath . "/plugins.php"); }
/** * @test */ public function vpconfigDoesntAllowDirectAccess() { $pluginsDir = self::$wpAutomation->getPluginsDir(); $relativePathToPluginsDir = PathUtils::getRelativePath(self::$wpAutomation->getWebRoot(), $pluginsDir); $url = self::$testConfig->testSite->url . '/' . $relativePathToPluginsDir . "/versionpress/vpconfig.yml"; $statusCode = HttpStatusCodeUtil::getStatusCode($url); $this->assertTrue($statusCode === 403 || $statusCode === 404, "Wrong HTTP status code ({$statusCode})"); }
public function __construct($name = null, array $data = [], $dataName = '') { parent::__construct($name, $data, $dataName); $this->staticInitialization(); $this->gitRepository = new GitRepository(self::$testConfig->testSite->path); self::$wpAutomation = new WpAutomation(self::$testConfig->testSite, self::$testConfig->wpCliVersion); $vpdbDir = self::$wpAutomation->getVpdbDir(); $relativePathToVpdb = PathUtils::getRelativePath(self::$testConfig->testSite->path, $vpdbDir); $uploadsDir = self::$wpAutomation->getUploadsDir(); $relativePathToUploads = PathUtils::getRelativePath(self::$testConfig->testSite->path, $uploadsDir); $dbSchema = new DbSchemaInfo([self::$wpAutomation->getPluginsDir() . '/versionpress/.versionpress/schema.yml'], self::$testConfig->testSite->dbTablePrefix, PHP_INT_MAX); $actionsInfoProvider = new ActionsInfoProvider([self::$wpAutomation->getPluginsDir() . '/versionpress/.versionpress/actions.yml']); $this->commitAsserter = new CommitAsserter($this->gitRepository, $dbSchema, $actionsInfoProvider, ['vpdb' => $relativePathToVpdb, 'uploads' => $relativePathToUploads]); }
/** * @test * @dataProvider specialPathsProvider */ public function specialPaths($from, $to, $expected) { $relativePath = PathUtils::getRelativePath($from, $to); $this->assertEquals($expected, $relativePath, "Wrong relative path from: '{$from}' to: '{$to}'."); }
/** * Returns relative path of given path to the WP site. * * @param $absolutePath * @return string */ protected function getRelativePath($absolutePath) { return PathUtils::getRelativePath($this->testConfig->testSite->path, $absolutePath); }
/** * Uninstalls a merge driver - removes 'vp-ini' sections from both .gitattributes * and .git/config. * * @param string $rootDir * @param string $pluginDir * @param string $vpdbDir */ public static function uninstallMergeDriver($rootDir, $pluginDir, $vpdbDir) { $gitconfigPath = $rootDir . '/.git/config'; $gitattributesPath = $rootDir . '/.gitattributes'; $gitattributesContents = file_get_contents($pluginDir . '/src/Initialization/.gitattributes.tpl'); $gitattributesVariables = ['vpdb-dir' => PathUtils::getRelativePath($rootDir, $vpdbDir)]; $gitattributesContents = StringUtils::fillTemplateString($gitattributesVariables, $gitattributesContents); if (file_exists($gitattributesPath)) { $gitAttributes = file_get_contents($gitattributesPath); $gitAttributes = str_replace($gitattributesContents, '', $gitAttributes); if (trim($gitAttributes) === '') { unlink($gitattributesPath); } else { file_put_contents($gitattributesPath, $gitAttributes); } } if (file_exists($gitconfigPath)) { $gitConfig = file_get_contents($gitconfigPath); // https://regex101.com/r/eJ4rJ5/4 $mergeDriverRegex = "/(\\[merge \\\"vp\\-ini\\\"\\]\\r?\\n)([^\\[]*)/"; $gitConfig = preg_replace($mergeDriverRegex, '', $gitConfig, 1); file_put_contents($gitconfigPath, $gitConfig); } }
/** * Installs Gitignore to the repository root, or does nothing if the file already exists. */ private function installGitignore() { $gitignorePath = VP_PROJECT_ROOT . '/.gitignore'; $projectRoot = realpath(VP_PROJECT_ROOT); $vpGitignore = file_get_contents(__DIR__ . '/.gitignore.tpl'); $gitIgnoreVariables = ['wp-content' => rtrim('/' . PathUtils::getRelativePath($projectRoot, realpath(WP_CONTENT_DIR)), '/'), 'wp-plugins' => rtrim('/' . PathUtils::getRelativePath($projectRoot, realpath(WP_PLUGIN_DIR)), '/'), 'abspath' => rtrim('/' . PathUtils::getRelativePath($projectRoot, realpath(ABSPATH)), '/'), 'abspath-parent' => rtrim('/' . PathUtils::getRelativePath($projectRoot, realpath(dirname(ABSPATH))), '/')]; $vpGitignore = StringUtils::fillTemplateString($gitIgnoreVariables, $vpGitignore); if (is_file($gitignorePath)) { $currentGitignore = file_get_contents($gitignorePath); if (strpos($currentGitignore, $vpGitignore) !== false) { return; } file_put_contents($gitignorePath, "\n" . $vpGitignore, FILE_APPEND); } else { file_put_contents($gitignorePath, $vpGitignore); } }
/** * Clones site to a new folder and database. * * ## OPTIONS * * --name=<name> * : Name of the clone. Used as a directory name, part of the DB prefix * and an argument to the pull & push commands later. * * [--siteurl=<url>] * : URL of the clone. By default, the original URL is searched for <cwd> * and replaced with the clone name. * * [--dbname=<dbname>] * : Database name for the clone. * * [--dbuser=<dbuser>] * : Database user for the clone. * * [--dbpass=<dbpass>] * : Database user password for the clone. * * [--dbhost=<dbhost>] * : Database host for the clone. * * [--dbprefix=<dbprefix>] * : Database table prefix for the clone. * * [--dbcharset=<dbcharset>] * : Database charset for the clone. * * [--dbcollate=<dbcollate>] * : Database collation for the clone. * * [--force] * : Forces cloning even if the target directory or DB tables exists. * Basically provides --yes to all warnings / confirmations. * * [--yes] * : Another way to force the clone * * ## EXAMPLES * * The main site lives in a directory 'wpsite', uses the 'wp_' database table prefix and is * accessible via 'http://localhost/wpsite'. The command * * wp vp clone --name=myclone * * does the following: * * - Creates new directory 'myclone' next to the current one * - Clones the files there * - Creates new database tables prefixed with 'wp_myclone_' * - Populates database tables with data * - Makes the site accessible as 'http://localhost/myclone' * * * @subcommand clone * */ public function cloneSite($args = [], $assoc_args = []) { global $table_prefix; if (isset($assoc_args['force'])) { $assoc_args['yes'] = 1; } if (!VersionPress::isActive()) { WP_CLI::error('This site is not tracked by VersionPress. Please run "wp vp activate" before cloning.'); } $name = $assoc_args['name']; if (!WorkflowUtils::isCloneNameValid($name)) { // @codingStandardsIgnoreLine WP_CLI::error("Clone name '{$name}' is not valid. It can only contain letters, numbers, hyphens and underscores."); } $currentWpPath = realpath(VP_PROJECT_ROOT); $cloneDirName = $name; $clonePath = dirname($currentWpPath) . '/' . $cloneDirName; $cloneVpPluginPath = $clonePath . '/' . str_replace($currentWpPath, '', realpath(VERSIONPRESS_PLUGIN_DIR)); $cloneDbUser = isset($assoc_args['dbuser']) ? $assoc_args['dbuser'] : DB_USER; $cloneDbPassword = isset($assoc_args['dbpass']) ? $assoc_args['dbpass'] : DB_PASSWORD; $cloneDbName = isset($assoc_args['dbname']) ? $assoc_args['dbname'] : DB_NAME; $cloneDbHost = isset($assoc_args['dbhost']) ? $assoc_args['dbhost'] : DB_HOST; $cloneDbPrefix = isset($assoc_args['dbprefix']) ? $assoc_args['dbprefix'] : $table_prefix . $name . '_'; $cloneDbCharset = isset($assoc_args['dbcharset']) ? $assoc_args['dbcharset'] : DB_CHARSET; $cloneDbCollate = isset($assoc_args['dbcollate']) ? $assoc_args['dbcollate'] : DB_COLLATE; // Checking the DB prefix, regex from wp-admin/setup-config.php if (isset($assoc_args['dbprefix']) && preg_match('|[^a-z0-9_]|i', $cloneDbPrefix)) { // @codingStandardsIgnoreLine WP_CLI::error("Table prefix '{$cloneDbPrefix}' is not valid. It can only contain letters, numbers and underscores. Please choose different one."); } $prefixChanged = false; if (Strings::contains($cloneDbPrefix, '-')) { $cloneDbPrefix = str_replace('-', '_', $cloneDbPrefix); $prefixChanged = true; } $currentUrl = get_home_url(); $suggestedUrl = $this->suggestCloneUrl($currentUrl, basename($currentWpPath), $cloneDirName); if (!$suggestedUrl && !isset($assoc_args['siteurl'])) { WP_CLI::error("The command cannot derive default clone URL. Please specify the --siteurl parameter."); } $cloneUrl = isset($assoc_args['siteurl']) ? $assoc_args['siteurl'] : $suggestedUrl; $urlChanged = !isset($assoc_args['siteurl']) && !Strings::contains($cloneUrl, $cloneDirName); if (is_dir($clonePath)) { // @codingStandardsIgnoreLine WP_CLI::confirm("Directory '" . basename($clonePath) . "' already exists, it will be deleted before cloning. Proceed?", $assoc_args); } if ($this->someWpTablesExist($cloneDbUser, $cloneDbPassword, $cloneDbName, $cloneDbHost, $cloneDbPrefix)) { // @codingStandardsIgnoreLine WP_CLI::confirm("Database tables for the clone already exist, they will be dropped and re-created. Proceed?", $assoc_args); } if (is_dir($clonePath)) { try { FileSystem::removeContent($clonePath); } catch (IOException $e) { WP_CLI::error("Could not delete directory '" . basename($clonePath) . "'. Please do it manually."); } } vp_commit_all_frequently_written_entities(); // Clone the site $cloneCommand = sprintf("git clone %s %s", ProcessUtils::escapeshellarg($currentWpPath), ProcessUtils::escapeshellarg($clonePath)); $process = VPCommandUtils::exec($cloneCommand, $currentWpPath); if (!$process->isSuccessful()) { WP_CLI::error($process->getConsoleOutput(), false); WP_CLI::error("Cloning Git repo failed"); } else { WP_CLI::success("Site files cloned"); } // Adding the clone as a remote for the convenience of the `vp pull` command - its `--from` // parameter can then be just the name of the clone, not a path to it $addRemoteCommand = sprintf("git remote add %s %s", ProcessUtils::escapeshellarg($name), ProcessUtils::escapeshellarg($clonePath)); $process = VPCommandUtils::exec($addRemoteCommand, $currentWpPath); if (!$process->isSuccessful()) { // @codingStandardsIgnoreLine $overwriteRemote = VPCommandUtils::cliQuestion("The Git repo of this site already defines remote '{$name}', overwrite it?", ["y", "n"], $assoc_args); if ($overwriteRemote == "y") { $addRemoteCommand = str_replace(" add ", " set-url ", $addRemoteCommand); $process = VPCommandUtils::exec($addRemoteCommand, $currentWpPath); if (!$process->isSuccessful()) { WP_CLI::error("Could not update remote's URL"); } else { WP_CLI::success("Updated remote configuration"); } } } else { WP_CLI::success("Clone added as a remote"); } // Enable pushing to origin $configCommand = "git config receive.denyCurrentBranch ignore"; $process = VPCommandUtils::exec($configCommand); if ($process->isSuccessful()) { WP_CLI::success("Enabled pushing to the original repository"); } else { WP_CLI::error("Cannot enable pushing to the original repository"); } // Enable pushing to clone $configCommand = "git config receive.denyCurrentBranch ignore"; $process = VPCommandUtils::exec($configCommand, $clonePath); if ($process->isSuccessful()) { WP_CLI::success("Enabled pushing to the clone"); } else { WP_CLI::error("Cannot enable pushing to the clone"); } // Copy & Update wp-config $wpConfigFile = \WP_CLI\Utils\locate_wp_config(); $cloneConfigFile = str_replace($currentWpPath, $clonePath, $wpConfigFile); copy($wpConfigFile, $cloneConfigFile); $this->updateConfig($clonePath, $name, $cloneDbUser, $cloneDbPassword, $cloneDbName, $cloneDbHost, $cloneDbPrefix, $cloneDbCharset, $cloneDbCollate); // Copy VersionPress FileSystem::copyDir(VERSIONPRESS_PLUGIN_DIR, $cloneVpPluginPath); WP_CLI::success("Copied VersionPress"); // Finish the process by doing the standard restore-site $relativePathToThisFile = PathUtils::getRelativePath($currentWpPath, __FILE__); $process = VPCommandUtils::runWpCliCommand('vp', 'restore-site', ['siteurl' => $cloneUrl, 'yes' => null, 'require' => $relativePathToThisFile], $clonePath); WP_CLI::log(trim($process->getConsoleOutput())); if ($process->isSuccessful()) { WP_CLI::success("All done. Clone created here:"); WP_CLI::log(""); WP_CLI::log("Path: {$clonePath}"); WP_CLI::log("URL: {$cloneUrl}"); if ($urlChanged) { WP_CLI::log("Note: Underscores changed to hyphens for URL."); } if ($prefixChanged) { WP_CLI::log("Note: Hyphens changed to underscores for DB prefix."); } } }
public function prepare_setFeaturedImageForUnsavedPost() { $this->url($this->getPostTypeScreenUrl()); $addNewSelector = $this->isWpVersionLowerThan('4.3-alpha1') ? '.edit-php #wpbody-content .wrap a.add-new-h2' : '.edit-php #wpbody-content .wrap a.page-title-action'; $this->byCssSelector($addNewSelector)->click(); $this->waitAfterRedirect(); $attachments = json_decode(self::$wpAutomation->runWpCliCommand('post', 'list', ['post_type' => 'attachment', 'format' => 'json'])); if (count($attachments) > 0) { return; } $imagePath = PathUtils::getRelativePath(self::$testConfig->testSite->path, __DIR__ . '/../test-data/test.png'); self::$wpAutomation->importMedia($imagePath); }