/** * Restores a WP site from Git repo / working directory. * * ## OPTIONS * * --siteurl=<url> * : The address of the restored site. Default: 'http://localhost/<cwd>' * * --dbname=<dbname> * : Set the database name. * * --dbuser=<dbuser> * : Set the database user. * * --dbpass=<dbpass> * : Set the database user password. * * --dbhost=<dbhost> * : Set the database host. Default: 'localhost' * * --dbprefix=<dbprefix> * : Set the database table prefix. Default: 'wp_' * * --dbcharset=<dbcharset> * : Set the database charset. Default: 'utf8' * * --dbcollate=<dbcollate> * : Set the database collation. Default: '' * * --yes * : Answer yes to the confirmation message. * * ## DESCRIPTION * * The simplest possible example just executes `site-restore` without any parameters. * The assumptions are: * * * The current directory must be reachable from the webserver as http://localhost/<cwd> * * Credentials for the MySQL server are in the wp-config.php * * The command will then do the following: * * * Create a db <dirname>, e.g., 'vp01' * * Optionally configure WordPress to connect to this DB * * Create WordPress tables in it and preconfigure it with site_url and home options * * Run VP synchronizers on the database * * All DB credentials and site URL are configurable. * * @synopsis [--siteurl=<url>] [--dbname=<dbname>] [--dbuser=<dbuser>] [--dbpass=<dbpass>] [--dbhost=<dbhost>] [--dbprefix=<dbprefix>] [--dbcharset=<dbcharset>] [--dbcollate=<dbcollate>] [--yes] * * @subcommand restore-site * * @when before_wp_load */ public function restoreSite($args, $assoc_args) { // Load VersionPress' bootstrap (WP_CONTENT_DIR needs to be defined) if (!defined('WP_CONTENT_DIR')) { define('WP_CONTENT_DIR', ABSPATH . 'wp-content'); } require_once __DIR__ . '/../../bootstrap.php'; // Check if the site is installed $process = VPCommandUtils::runWpCliCommand('core', 'is-installed'); if ($process->isSuccessful()) { WP_CLI::confirm("It looks like the site is OK. Do you really want to run the 'restore-site' command?", $assoc_args); $defaultUrl = trim(VPCommandUtils::runWpCliCommand('option', 'get', array('siteurl'))->getConsoleOutput()); } else { $defaultUrl = 'http://localhost/' . basename(getcwd()); } $url = @$assoc_args['siteurl'] ?: $defaultUrl; // Confirm automatically chosen site URL if (!isset($assoc_args['siteurl'])) { WP_CLI::confirm("The site URL will be set to '{$url}'. Proceed?", $assoc_args); } // Updating wp-config.php if (file_exists(ABSPATH . 'wp-config.php')) { if ($this->issetConfigOption($assoc_args)) { WP_CLI::error("Site settings was loaded from wp-config.php. If you want to reconfigure the site, please delete the wp-config.php file"); } } else { $this->configSite($assoc_args); } // Create or empty database $this->prepareDatabase($assoc_args); // Disable VersionPress tracking if (!defined('WPINC')) { define('WPINC', 'wp-includes'); } WpdbReplacer::restoreOriginal(); unlink(VERSIONPRESS_ACTIVATION_FILE); // Create WP tables. The only important thing is site URL, all else will be rewritten later during synchronization. $installArgs = array('url' => $url, 'title' => 'x', 'admin_user' => 'x', 'admin_password' => 'x', 'admin_email' => '*****@*****.**'); $process = VPCommandUtils::runWpCliCommand('core', 'install', $installArgs); if (!$process->isSuccessful()) { WP_CLI::log("Failed creating database tables"); WP_CLI::error($process->getConsoleOutput()); } else { WP_CLI::success("Database tables created"); } // Restores "wp-db.php", "wp-db.php.original" and ".active" $resetCmd = 'git reset --hard'; $process = VPCommandUtils::exec($resetCmd); if (!$process->isSuccessful()) { WP_CLI::log("Could not clean working directory"); WP_CLI::error($process->getConsoleOutput()); } // The next couple of the steps need to be done after the WP is fully loaded; we use `finish-init-clone` for that // The main reason for this is that we need properly set WP_CONTENT_DIR constant for reading from storages $process = VPCommandUtils::runWpCliCommand('vp-internal', 'finish-init-clone', array('require' => $this->getVPInternalCommandPath())); WP_CLI::log($process->getConsoleOutput()); if (!$process->isSuccessful()) { WP_CLI::error("Could not finish site restore"); } }
/** * 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; } }
/** * 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")); } }
private function activateVersionPress() { WpdbReplacer::replaceMethods(); touch(VERSIONPRESS_ACTIVATION_FILE); $this->reportProgressChange(InitializerStates::VERSIONPRESS_ACTIVATED); }
/** * Restores a WP site from Git repo / working directory. * * ## OPTIONS * * --siteurl=<url> * : The address of the restored site. * * [--yes] * : Answer yes to the confirmation message. * * ## DESCRIPTION * * The command will then do the following: * * * Drops all tables tracked by VersionPress. * * Recreates and fill them with data from repository. * * If you just cloned the site from another repository, run `wp core config` first. * * * @subcommand restore-site * * @when before_wp_load */ public function restoreSite($args, $assoc_args) { if (file_exists(getcwd() . '/composer.json')) { $proc = proc_open("composer install", [1 => ["pipe", "w"], ["pipe", "w"]], $_); $result = proc_close($proc); if ($result !== 0) { WP_CLI::error('Composer dependencies could not be restored.'); } } defined('SHORTINIT') or define('SHORTINIT', true); require_once __DIR__ . '/../Initialization/WpConfigSplitter.php'; $wpConfigPath = \WP_CLI\Utils\locate_wp_config(); $this->requireWpConfig($wpConfigPath, WpConfigSplitter::COMMON_CONFIG_NAME); require_once __DIR__ . '/../../bootstrap.php'; if (!VersionPress::isActive()) { WP_CLI::error('Unfortunately, this site was not tracked by VersionPress. Therefore, it cannot be restored.'); } // Check if the site is installed $process = VPCommandUtils::runWpCliCommand('core', 'is-installed'); if ($process->isSuccessful()) { $this->checkVpRequirements($assoc_args, RequirementsChecker::ENVIRONMENT); WP_CLI::confirm("It looks like the site is OK. Do you really want to run the 'restore-site' command?", $assoc_args); } $url = $assoc_args['siteurl']; // Update URLs in wp-config.php define('VP_INDEX_DIR', dirname(\WP_CLI\Utils\locate_wp_config())); // just for the following method $this->setConfigUrl('WP_CONTENT_URL', 'WP_CONTENT_DIR', ABSPATH . 'wp-content', $url); $this->setConfigUrl('WP_PLUGIN_URL', 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins', $url); $this->setConfigUrl('WP_HOME', 'VP_INDEX_DIR', VP_PROJECT_ROOT, $url); defined('WP_PLUGIN_DIR') || define('WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins'); WpConfigSplitter::ensureCommonConfigInclude($wpConfigPath); // Disable VersionPress tracking for a while WpdbReplacer::restoreOriginal(); unlink(VERSIONPRESS_ACTIVATION_FILE); // Create or empty database $this->prepareDatabase($assoc_args); // Create WP tables. // The only important thing is site URL, all else will be rewritten later during synchronization. $installArgs = ['url' => $url, 'title' => 'x', 'admin_user' => 'x', 'admin_password' => 'x', 'admin_email' => '*****@*****.**']; if (version_compare(WP_CLI_VERSION, '0.22.0', '>=')) { $installArgs['skip-email'] = null; } $process = VPCommandUtils::runWpCliCommand('core', 'install', $installArgs); if (!$process->isSuccessful()) { WP_CLI::log("Failed creating database tables"); WP_CLI::error($process->getConsoleOutput()); } else { WP_CLI::success("Database tables created"); } // Restores "wp-db.php", "wp-db.php.original" and ".active" - enables VP $resetCmd = 'git reset --hard'; $process = VPCommandUtils::exec($resetCmd); if (!$process->isSuccessful()) { WP_CLI::log("Could not clean working directory"); WP_CLI::error($process->getConsoleOutput()); } // Fail-safe for gitignored WordPress if (!WpdbReplacer::isReplaced()) { WpdbReplacer::replaceMethods(); } /* We need correct value in the `active_plugins` option before the synchronization run. * Without this option VersionPress doesn't know which schema.yml files it should load and consequently which * DB entities it should synchronize. */ $activePluginsOption = IniSerializer::deserialize(file_get_contents(VP_VPDB_DIR . '/options/ac/active_plugins.ini')); $activePlugins = json_encode(unserialize($activePluginsOption['active_plugins']['option_value'])); VPCommandUtils::runWpCliCommand('option', 'update', ['active_plugins', $activePlugins, 'autoload' => 'yes', 'format' => 'json', 'skip-plugins' => null]); // The next couple of the steps need to be done after WP is fully loaded; we use `finish-restore-site` for that // The main reason for this is that we need properly set WP_CONTENT_DIR constant for reading from storages $process = $this->runVPInternalCommand('finish-restore-site'); WP_CLI::log($process->getConsoleOutput()); if (!$process->isSuccessful()) { WP_CLI::error("Could not finish site restore"); } }
add_filter('vp_entity_files_composer', function ($files) { $files[] = ["type" => "path", "path" => VP_PROJECT_ROOT . '/composer.json']; $files[] = ["type" => "path", "path" => VP_PROJECT_ROOT . '/composer.lock']; return $files; }); add_action('vp_wordpress_updated', function ($version) { global $versionPressContainer; $wpFiles = [["type" => "path", "path" => "index.php"], ["type" => "path", "path" => "license.txt"], ["type" => "path", "path" => "readme.html"], ["type" => "path", "path" => "wp-activate.php"], ["type" => "path", "path" => "wp-blog-header.php"], ["type" => "path", "path" => "wp-comments-post.php"], ["type" => "path", "path" => "wp-config-sample.php"], ["type" => "path", "path" => "wp-cron.php"], ["type" => "path", "path" => "wp-links-opml.php"], ["type" => "path", "path" => "wp-load.php"], ["type" => "path", "path" => "wp-login.php"], ["type" => "path", "path" => "wp-mail.php"], ["type" => "path", "path" => "wp-settings.php"], ["type" => "path", "path" => "wp-signup.php"], ["type" => "path", "path" => "wp-trackback.php"], ["type" => "path", "path" => "xmlrpc.php"], ["type" => "path", "path" => ABSPATH . WPINC . '/*'], ["type" => "path", "path" => ABSPATH . 'wp-admin/*'], ["type" => "path", "path" => WP_CONTENT_DIR . '/themes/twenty*'], ["type" => "path", "path" => WP_CONTENT_DIR . '/languages/*'], ["type" => "path", "path" => VP_VPDB_DIR . '/.schema/*'], ["type" => "path", "path" => VP_PROJECT_ROOT . '/composer.json'], ["type" => "path", "path" => VP_PROJECT_ROOT . '/composer.lock']]; /** @var DbSchemaInfo $dbSchema */ $dbSchema = $versionPressContainer->resolve(VersionPressServices::DB_SCHEMA); $tableSchemaStorage = $versionPressContainer->resolve(VersionPressServices::TABLE_SCHEMA_STORAGE); $dbSchema->refreshDbSchema(new ActivePluginsVPFilesIterator('schema.yml')); vp_update_table_ddl_scripts($dbSchema, $tableSchemaStorage); vp_force_action('wordpress', 'update', $version, [], $wpFiles); if (!WpdbReplacer::isReplaced()) { WpdbReplacer::replaceMethods(); } }); add_action('vp_plugin_changed', function ($action, $pluginFile, $pluginName) { global $versionPressContainer; /** @var DbSchemaInfo $dbSchema */ $dbSchema = $versionPressContainer->resolve(VersionPressServices::DB_SCHEMA); $tableSchemaStorage = $versionPressContainer->resolve(VersionPressServices::TABLE_SCHEMA_STORAGE); $dbSchema->refreshDbSchema(new ActivePluginsVPFilesIterator('schema.yml')); vp_update_table_ddl_scripts($dbSchema, $tableSchemaStorage); if ($action !== 'delete') { /** @var ActionsDefinitionRepository $actionsDefinitionRepository */ $actionsDefinitionRepository = $versionPressContainer->resolve(VersionPressServices::ACTIONS_DEFINITION_REPOSITORY); $actionsDefinitionRepository->saveDefinitionForPlugin($pluginFile); } $pluginPath = WP_PLUGIN_DIR . "/";