Linux iad1-shared-b7-18 6.6.49-grsec-jammy+ #10 SMP Thu Sep 12 23:23:08 UTC 2024 x86_64
Apache
: 67.205.6.31 | : 216.73.216.47
Cant Read [ /etc/named.conf ]
8.2.29
fernandoquevedo
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
README
+ Create Folder
+ Create File
/
usr /
local /
wp /
vendor /
wp-cli /
core-command /
src /
[ HOME SHELL ]
Name
Size
Permission
Action
WP_CLI
[ DIR ]
drwxr-xr-x
Core_Command.php
51.26
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : Core_Command.php
<?php use Composer\Semver\Comparator; use WP_CLI\Extractor; use WP_CLI\Iterators\Table as TableIterator; use WP_CLI\Utils; use WP_CLI\Formatter; use WP_CLI\WpOrgApi; /** * Downloads, installs, updates, and manages a WordPress installation. * * ## EXAMPLES * * # Download WordPress core * $ wp core download --locale=nl_NL * Downloading WordPress 4.5.2 (nl_NL)... * md5 hash verified: c5366d05b521831dd0b29dfc386e56a5 * Success: WordPress downloaded. * * # Install WordPress * $ wp core install --url=example.com --title=Example --admin_user=supervisor --admin_password=strongpassword --admin_email=info@example.com * Success: WordPress installed successfully. * * # Display the WordPress version * $ wp core version * 4.5.2 * * @package wp-cli */ class Core_Command extends WP_CLI_Command { /** * Checks for WordPress updates via Version Check API. * * Lists the most recent versions when there are updates available, * or success message when up to date. * * ## OPTIONS * * [--minor] * : Compare only the first two parts of the version number. * * [--major] * : Compare only the first part of the version number. * * [--force-check] * : Bypass the transient cache and force a fresh update check. * * [--field=<field>] * : Prints the value of a single field for each update. * * [--fields=<fields>] * : Limit the output to specific object fields. Defaults to version,update_type,package_url. * * [--format=<format>] * : Render output in a particular format. * --- * default: table * options: * - table * - csv * - count * - json * - yaml * --- * * ## EXAMPLES * * $ wp core check-update * +---------+-------------+-------------------------------------------------------------+ * | version | update_type | package_url | * +---------+-------------+-------------------------------------------------------------+ * | 4.5.2 | major | https://downloads.wordpress.org/release/wordpress-4.5.2.zip | * +---------+-------------+-------------------------------------------------------------+ * * @subcommand check-update * * @param string[] $args Positional arguments. Unused. * @param array{minor?: bool, major?: bool, 'force-check'?: bool, field?: string, format: string} $assoc_args Associative arguments. */ public function check_update( $args, $assoc_args ) { $format = Utils\get_flag_value( $assoc_args, 'format', 'table' ); $updates = $this->get_updates( $assoc_args ); if ( $updates || 'table' !== $format ) { $updates = array_reverse( $updates ); $formatter = new Formatter( $assoc_args, [ 'version', 'update_type', 'package_url' ] ); $formatter->display_items( $updates ); } else { WP_CLI::success( 'WordPress is at the latest version.' ); } } /** * Downloads core WordPress files. * * Downloads and extracts WordPress core files to the specified path. Uses * current directory when no path is specified. Downloaded build is verified * to have the correct md5 and then cached to the local filesystem. * Subsequent uses of command will use the local cache if it still exists. * * ## OPTIONS * * [<download-url>] * : Download directly from a provided URL instead of fetching the URL from the wordpress.org servers. * * [--path=<path>] * : Specify the path in which to install WordPress. Defaults to current * directory. * * [--locale=<locale>] * : Select which language you want to download. * * [--version=<version>] * : Select which version you want to download. Accepts a version number, 'latest' or 'nightly'. * * [--skip-content] * : Download WP without the default themes and plugins. * * [--force] * : Overwrites existing files, if present. * * [--insecure] * : Retry download without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * * [--extract] * : Whether to extract the downloaded file. Defaults to true. * * ## EXAMPLES * * $ wp core download --locale=nl_NL * Downloading WordPress 4.5.2 (nl_NL)... * md5 hash verified: c5366d05b521831dd0b29dfc386e56a5 * Success: WordPress downloaded. * * @when before_wp_load * * @param array{0?: string} $args Positional arguments. * @param array{path?: string, locale?: string, version?: string, 'skip-content'?: bool, force?: bool, insecure?: bool, extract?: bool} $assoc_args Associative arguments. */ public function download( $args, $assoc_args ) { /** * @var string $download_dir */ $download_dir = ! empty( $assoc_args['path'] ) ? ( rtrim( $assoc_args['path'], '/\\' ) . '/' ) : ABSPATH; // Check for files if WordPress already present or not. $wordpress_present = is_readable( $download_dir . 'wp-load.php' ) || is_readable( $download_dir . 'wp-mail.php' ) || is_readable( $download_dir . 'wp-cron.php' ) || is_readable( $download_dir . 'wp-links-opml.php' ); if ( $wordpress_present && ! Utils\get_flag_value( $assoc_args, 'force' ) ) { WP_CLI::error( 'WordPress files seem to already be present here.' ); } if ( ! is_dir( $download_dir ) ) { if ( ! is_writable( dirname( $download_dir ) ) ) { WP_CLI::error( "Insufficient permission to create directory '{$download_dir}'." ); } WP_CLI::log( "Creating directory '{$download_dir}'." ); if ( ! @mkdir( $download_dir, 0777, true /*recursive*/ ) ) { $error = error_get_last(); if ( $error ) { WP_CLI::error( "Failed to create directory '{$download_dir}': {$error['message']}." ); } else { WP_CLI::error( "Failed to create directory '{$download_dir}'." ); } } } if ( ! is_writable( $download_dir ) ) { WP_CLI::error( "'{$download_dir}' is not writable by current user." ); } $locale = Utils\get_flag_value( $assoc_args, 'locale', 'en_US' ); $skip_content = Utils\get_flag_value( $assoc_args, 'skip-content', false ); $insecure = Utils\get_flag_value( $assoc_args, 'insecure', false ); $extract = Utils\get_flag_value( $assoc_args, 'extract', true ); if ( $skip_content && ! $extract ) { WP_CLI::error( 'Cannot use both --skip-content and --no-extract at the same time.' ); } $download_url = array_shift( $args ); $from_url = ! empty( $download_url ); if ( $from_url ) { $version = null; if ( isset( $assoc_args['version'] ) ) { WP_CLI::error( 'Version option is not available for URL downloads.' ); } if ( $skip_content || 'en_US' !== $locale ) { WP_CLI::error( 'Skip content and locale options are not available for URL downloads.' ); } } elseif ( isset( $assoc_args['version'] ) && 'latest' !== $assoc_args['version'] ) { $version = $assoc_args['version']; if ( in_array( strtolower( $version ), [ 'trunk', 'nightly' ], true ) ) { $version = 'nightly'; } // Nightly builds and skip content are only available in .zip format. $extension = ( ( 'nightly' === $version ) || $skip_content ) ? 'zip' : 'tar.gz'; $download_url = $this->get_download_url( $version, $locale, $extension ); } else { try { $offer = ( new WpOrgApi( [ 'insecure' => $insecure ] ) ) ->get_core_download_offer( $locale ); } catch ( Exception $exception ) { WP_CLI::error( $exception ); } if ( ! $offer ) { WP_CLI::error( "The requested locale ({$locale}) was not found." ); } $version = $offer['current']; $download_url = $offer['download']; if ( ! $skip_content ) { $download_url = str_replace( '.zip', '.tar.gz', $download_url ); } } if ( 'nightly' === $version && 'en_US' !== $locale ) { WP_CLI::error( 'Nightly builds are only available for the en_US locale.' ); } $from_version = ''; if ( file_exists( $download_dir . 'wp-includes/version.php' ) ) { $wp_details = self::get_wp_details( $download_dir ); $from_version = $wp_details['wp_version']; } if ( $from_url ) { WP_CLI::log( "Downloading from {$download_url} ..." ); } else { WP_CLI::log( "Downloading WordPress {$version} ({$locale})..." ); } $path_parts = pathinfo( $download_url ); $extension = 'tar.gz'; if ( isset( $path_parts['extension'] ) && 'zip' === $path_parts['extension'] ) { $extension = 'zip'; if ( $extract && ! class_exists( 'ZipArchive' ) ) { WP_CLI::error( 'Extracting a zip file requires ZipArchive.' ); } } if ( $skip_content && 'zip' !== $extension ) { WP_CLI::error( 'Skip content is only available for ZIP files.' ); } $cache = WP_CLI::get_cache(); if ( $from_url ) { $cache_file = null; } else { $cache_key = "core/wordpress-{$version}-{$locale}.{$extension}"; $cache_file = $cache->has( $cache_key ); } $bad_cache = false; if ( is_string( $cache_file ) ) { WP_CLI::log( "Using cached file '{$cache_file}'..." ); $skip_content_cache_file = $skip_content ? self::strip_content_dir( $cache_file ) : null; if ( $extract ) { try { Extractor::extract( $skip_content_cache_file ?: $cache_file, $download_dir ); } catch ( Exception $exception ) { WP_CLI::warning( 'Extraction failed, downloading a new copy...' ); $bad_cache = true; } } else { copy( $cache_file, $download_dir . basename( $cache_file ) ); } } if ( ! $cache_file || $bad_cache ) { // We need to use a temporary file because piping from cURL to tar is flaky // on MinGW (and probably in other environments too). $temp = Utils\get_temp_dir() . uniqid( 'wp_' ) . ".{$extension}"; register_shutdown_function( function () use ( $temp ) { if ( file_exists( $temp ) ) { unlink( $temp ); } } ); $headers = [ 'Accept' => 'application/json' ]; $options = [ 'timeout' => 600, // 10 minutes ought to be enough for everybody 'filename' => $temp, 'insecure' => $insecure, ]; /** @var \WpOrg\Requests\Response $response */ $response = Utils\http_request( 'GET', $download_url, null, $headers, $options ); if ( 404 === (int) $response->status_code ) { WP_CLI::error( 'Release not found. Double-check locale or version.' ); } elseif ( 20 !== (int) substr( (string) $response->status_code, 0, 2 ) ) { WP_CLI::error( "Couldn't access download URL (HTTP code {$response->status_code})." ); } if ( 'nightly' !== $version ) { unset( $options['filename'] ); /** @var \WpOrg\Requests\Response $md5_response */ $md5_response = Utils\http_request( 'GET', $download_url . '.md5', null, [], $options ); if ( $md5_response->status_code >= 200 && $md5_response->status_code < 300 ) { $md5_file = md5_file( $temp ); if ( $md5_file === $md5_response->body ) { WP_CLI::log( 'md5 hash verified: ' . $md5_file ); } else { WP_CLI::error( "md5 hash for download ({$md5_file}) is different than the release hash ({$md5_response->body})." ); } } else { WP_CLI::warning( "Couldn't access md5 hash for release ({$download_url}.md5, HTTP code {$md5_response->status_code})." ); } } else { WP_CLI::warning( 'md5 hash checks are not available for nightly downloads.' ); } $skip_content_temp = $skip_content ? self::strip_content_dir( $temp ) : null; if ( $extract ) { try { Extractor::extract( $skip_content_temp ?: $temp, $download_dir ); } catch ( Exception $exception ) { WP_CLI::error( "Couldn't extract WordPress archive. {$exception->getMessage()}" ); } } else { copy( $temp, $download_dir . basename( $temp ) ); } // Do not use the cache for nightly builds or for downloaded URLs // (the URL could be something like "latest.zip" or "nightly.zip"). if ( ! $from_url && 'nightly' !== $version ) { $cache->import( $cache_key, $temp ); } } if ( $wordpress_present ) { $this->cleanup_extra_files( $from_version, $version, $locale, $insecure ); } WP_CLI::success( 'WordPress downloaded.' ); } /** * Checks if WordPress is installed. * * Determines whether WordPress is installed by checking if the standard * database tables are installed. Doesn't produce output; uses exit codes * to communicate whether WordPress is installed. * * ## OPTIONS * * [--network] * : Check if this is a multisite installation. * * ## EXAMPLES * * # Bash script for checking if WordPress is not installed. * * if ! wp core is-installed 2>/dev/null; then * # WP is not installed. Let's try installing it. * wp core install * fi * * # Bash script for checking if WordPress is installed, with fallback. * * if wp core is-installed 2>/dev/null; then * # WP is installed. Let's do some things we should only do in a confirmed WP environment. * wp core verify-checksums * else * # Fallback if WP is not installed. * echo 'Hey Friend, you are in the wrong spot. Move in to your WordPress directory and try again.' * fi * * @subcommand is-installed * * @param string[] $args Positional arguments. Unused. * @param array{network?: bool} $assoc_args Associative arguments. */ public function is_installed( $args, $assoc_args ) { if ( is_blog_installed() && ( ! Utils\get_flag_value( $assoc_args, 'network' ) || is_multisite() ) ) { WP_CLI::halt( 0 ); } WP_CLI::halt( 1 ); } /** * Runs the standard WordPress installation process. * * Creates the WordPress tables in the database using the URL, title, and * default admin user details provided. Performs the famous 5 minute install * in seconds or less. * * Note: if you've installed WordPress in a subdirectory, then you'll need * to `wp option update siteurl` after `wp core install`. For instance, if * WordPress is installed in the `/wp` directory and your domain is example.com, * then you'll need to run `wp option update siteurl http://example.com/wp` for * your WordPress installation to function properly. * * Note: When using custom user tables (e.g. `CUSTOM_USER_TABLE`), the admin * email and password are ignored if the user_login already exists. If the * user_login doesn't exist, a new user will be created. * * ## OPTIONS * * --url=<url> * : The address of the new site. * * --title=<site-title> * : The title of the new site. * * --admin_user=<username> * : The name of the admin user. * * [--admin_password=<password>] * : The password for the admin user. Defaults to randomly generated string. * * --admin_email=<email> * : The email address for the admin user. * * [--locale=<locale>] * : The locale/language for the installation (e.g. `de_DE`). Default is `en_US`. * * [--skip-email] * : Don't send an email notification to the new admin user. * * ## EXAMPLES * * # Install WordPress in 5 seconds * $ wp core install --url=example.com --title=Example --admin_user=supervisor --admin_password=strongpassword --admin_email=info@example.com * Success: WordPress installed successfully. * * # Install WordPress without disclosing admin_password to bash history * $ wp core install --url=example.com --title=Example --admin_user=supervisor --admin_email=info@example.com --prompt=admin_password < admin_password.txt * * @param string[] $args Positional arguments. Unused. * @param array{url: string, title: string, admin_user: string, admin_password?: string, admin_email: string, locale?: string, 'skip-email'?: bool} $assoc_args Associative arguments. */ public function install( $args, $assoc_args ) { if ( $this->do_install( $assoc_args ) ) { WP_CLI::success( 'WordPress installed successfully.' ); } else { WP_CLI::log( 'WordPress is already installed.' ); } } /** * Transforms an existing single-site installation into a multisite installation. * * Creates the multisite database tables, and adds the multisite constants * to wp-config.php. * * For those using WordPress with Apache, remember to update the `.htaccess` * file with the appropriate multisite rewrite rules. * * [Review the multisite documentation](https://wordpress.org/support/article/create-a-network/) * for more details about how multisite works. * * ## OPTIONS * * [--title=<network-title>] * : The title of the new network. * * [--base=<url-path>] * : Base path after the domain name that each site url will start with. * --- * default: / * --- * * [--subdomains] * : If passed, the network will use subdomains, instead of subdirectories. Doesn't work with 'localhost'. * * [--skip-config] * : Don't add multisite constants to wp-config.php. * * ## EXAMPLES * * $ wp core multisite-convert * Set up multisite database tables. * Added multisite constants to wp-config.php. * Success: Network installed. Don't forget to set up rewrite rules. * * @subcommand multisite-convert * @alias install-network * * @param string[] $args Positional arguments. Unused. * @param array{title?: string, base: string, subdomains?: bool, 'skip-config'?: bool} $assoc_args Associative arguments. */ public function multisite_convert( $args, $assoc_args ) { if ( is_multisite() ) { WP_CLI::error( 'This already is a multisite installation.' ); } $assoc_args = self::set_multisite_defaults( $assoc_args ); if ( ! isset( $assoc_args['title'] ) ) { /** * @var string $blogname */ $blogname = get_option( 'blogname' ); // translators: placeholder is blog name $assoc_args['title'] = sprintf( _x( '%s Sites', 'Default network name' ), $blogname ); } if ( $this->multisite_convert_( $assoc_args ) ) { WP_CLI::success( "Network installed. Don't forget to set up rewrite rules (and a .htaccess file, if using Apache)." ); } } /** * Installs WordPress multisite from scratch. * * Creates the WordPress tables in the database using the URL, title, and * default admin user details provided. Then, creates the multisite tables * in the database and adds multisite constants to the wp-config.php. * * For those using WordPress with Apache, remember to update the `.htaccess` * file with the appropriate multisite rewrite rules. * * ## OPTIONS * * [--url=<url>] * : The address of the new site. * * [--base=<url-path>] * : Base path after the domain name that each site url in the network will start with. * --- * default: / * --- * * [--subdomains] * : If passed, the network will use subdomains, instead of subdirectories. Doesn't work with 'localhost'. * * --title=<site-title> * : The title of the new site. * * --admin_user=<username> * : The name of the admin user. * --- * default: admin * --- * * [--admin_password=<password>] * : The password for the admin user. Defaults to randomly generated string. * * --admin_email=<email> * : The email address for the admin user. * * [--skip-email] * : Don't send an email notification to the new admin user. * * [--skip-config] * : Don't add multisite constants to wp-config.php. * * ## EXAMPLES * * $ wp core multisite-install --title="Welcome to the WordPress" \ * > --admin_user="admin" --admin_password="password" \ * > --admin_email="user@example.com" * Single site database tables already present. * Set up multisite database tables. * Added multisite constants to wp-config.php. * Success: Network installed. Don't forget to set up rewrite rules. * * @subcommand multisite-install * * @param string[] $args Positional arguments. Unused. * @param array{url?: string, base: string, subdomains?: bool, title: string, admin_user: string, admin_password?: string, admin_email: string, 'skip-email'?: bool, 'skip-config'?: bool} $assoc_args Associative arguments. */ public function multisite_install( $args, $assoc_args ) { if ( $this->do_install( $assoc_args ) ) { WP_CLI::log( 'Created single site database tables.' ); } else { WP_CLI::log( 'Single site database tables already present.' ); } $assoc_args = self::set_multisite_defaults( $assoc_args ); // translators: placeholder is user supplied title $assoc_args['title'] = sprintf( _x( '%s Sites', 'Default network name' ), $assoc_args['title'] ); // Overwrite runtime args, to avoid mismatches. $consts_to_args = [ 'SUBDOMAIN_INSTALL' => 'subdomains', 'PATH_CURRENT_SITE' => 'base', 'SITE_ID_CURRENT_SITE' => 'site_id', 'BLOG_ID_CURRENT_SITE' => 'blog_id', ]; foreach ( $consts_to_args as $const => $arg ) { if ( defined( $const ) ) { $assoc_args[ $arg ] = constant( $const ); } } if ( ! $this->multisite_convert_( $assoc_args ) ) { return; } // Do the steps that were skipped by populate_network(), // which checks is_multisite(). if ( is_multisite() ) { $site_user = get_user_by( 'email', $assoc_args['admin_email'] ); self::add_site_admins( $site_user ); $domain = self::get_clean_basedomain(); self::create_initial_blog( $assoc_args['site_id'], $assoc_args['blog_id'], $domain, $assoc_args['base'], $assoc_args['subdomains'], $site_user ); } WP_CLI::success( "Network installed. Don't forget to set up rewrite rules (and a .htaccess file, if using Apache)." ); } private static function set_multisite_defaults( $assoc_args ) { $defaults = [ 'subdomains' => false, 'base' => '/', 'site_id' => 1, 'blog_id' => 1, ]; return array_merge( $defaults, $assoc_args ); } private function do_install( $assoc_args ) { if ( is_blog_installed() ) { return false; } if ( true === Utils\get_flag_value( $assoc_args, 'skip-email' ) ) { if ( ! function_exists( 'wp_new_blog_notification' ) ) { // @phpstan-ignore function.inner function wp_new_blog_notification() { // Silence is golden } } // WP 4.9.0 - skip "Notice of Admin Email Change" email as well (https://core.trac.wordpress.org/ticket/39117). add_filter( 'send_site_admin_email_change_email', '__return_false' ); } require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $defaults = [ 'title' => '', 'admin_user' => '', 'admin_email' => '', 'admin_password' => '', ]; $defaults['locale'] = ''; $args = wp_parse_args( $assoc_args, $defaults ); // Support prompting for the `--url=<url>`, // which is normally a runtime argument if ( isset( $assoc_args['url'] ) ) { WP_CLI::set_url( $assoc_args['url'] ); } $public = true; $password = $args['admin_password']; if ( ! is_email( $args['admin_email'] ) ) { WP_CLI::error( "The '{$args['admin_email']}' email address is invalid." ); } $result = wp_install( $args['title'], $args['admin_user'], $args['admin_email'], $public, '', $password, $args['locale'] ); if ( ! empty( $GLOBALS['wpdb']->last_error ) ) { WP_CLI::error( 'Installation produced database errors, and may have partially or completely failed.' ); } if ( empty( $args['admin_password'] ) ) { WP_CLI::log( "Admin password: {$result['password']}" ); } // Confirm the uploads directory exists $upload_dir = wp_upload_dir(); if ( ! empty( $upload_dir['error'] ) ) { WP_CLI::warning( $upload_dir['error'] ); } return true; } private function multisite_convert_( $assoc_args ) { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $domain = self::get_clean_basedomain(); if ( 'localhost' === $domain && ! empty( $assoc_args['subdomains'] ) ) { WP_CLI::error( "Multisite with subdomains cannot be configured when domain is 'localhost'." ); } // need to register the multisite tables manually for some reason foreach ( $wpdb->tables( 'ms_global' ) as $table => $prefixed_table ) { $wpdb->$table = $prefixed_table; } install_network(); /** * @var string $admin_email */ $admin_email = get_option( 'admin_email' ); $result = populate_network( $assoc_args['site_id'], $domain, $admin_email, $assoc_args['title'], $assoc_args['base'], $assoc_args['subdomains'] ); $site_id = $wpdb->get_var( "SELECT id FROM $wpdb->site" ); $site_id = ( null === $site_id ) ? 1 : (int) $site_id; if ( true === $result ) { WP_CLI::log( 'Set up multisite database tables.' ); } else { switch ( $result->get_error_code() ) { case 'siteid_exists': WP_CLI::log( $result->get_error_message() ); return false; case 'no_wildcard_dns': WP_CLI::warning( __( 'Wildcard DNS may not be configured correctly.' ) ); break; default: WP_CLI::error( $result ); } } // delete_site_option() cleans the alloptions cache to prevent dupe option delete_site_option( 'upload_space_check_disabled' ); update_site_option( 'upload_space_check_disabled', 1 ); if ( ! is_multisite() ) { $subdomain_export = Utils\get_flag_value( $assoc_args, 'subdomains' ) ? 'true' : 'false'; $ms_config = <<<EOT define( 'WP_ALLOW_MULTISITE', true ); define( 'MULTISITE', true ); define( 'SUBDOMAIN_INSTALL', {$subdomain_export} ); \$base = '{$assoc_args['base']}'; define( 'DOMAIN_CURRENT_SITE', '{$domain}' ); define( 'PATH_CURRENT_SITE', '{$assoc_args['base']}' ); define( 'SITE_ID_CURRENT_SITE', {$site_id} ); define( 'BLOG_ID_CURRENT_SITE', 1 ); EOT; $wp_config_path = Utils\locate_wp_config(); if ( true === Utils\get_flag_value( $assoc_args, 'skip-config' ) ) { WP_CLI::log( "Addition of multisite constants to 'wp-config.php' skipped. You need to add them manually:\n{$ms_config}" ); } elseif ( is_writable( $wp_config_path ) && self::modify_wp_config( $ms_config ) ) { WP_CLI::log( "Added multisite constants to 'wp-config.php'." ); } else { WP_CLI::warning( "Multisite constants could not be written to 'wp-config.php'. You may need to add them manually:\n{$ms_config}" ); } } else { /* Multisite constants are defined, therefore we already have an empty site_admins site meta. * * Code based on parts of delete_network_option. */ $rows = $wpdb->get_results( "SELECT meta_id, site_id FROM {$wpdb->sitemeta} WHERE meta_key = 'site_admins' AND meta_value = ''" ); foreach ( $rows as $row ) { wp_cache_delete( "{$row->site_id}:site_admins", 'site-options' ); $wpdb->delete( $wpdb->sitemeta, [ 'meta_id' => $row->meta_id ] ); } } return true; } // copied from populate_network() private static function create_initial_blog( $network_id, $blog_id, $domain, $path, $subdomain_install, $site_user ) { global $wpdb, $current_site, $wp_rewrite; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- This is meant to replace Core functionality. $current_site = new stdClass(); $current_site->domain = $domain; $current_site->path = $path; $current_site->site_name = ucfirst( $domain ); $blog_data = [ 'site_id' => $network_id, 'domain' => $domain, 'path' => $path, 'registered' => current_time( 'mysql' ), ]; $wpdb->insert( $wpdb->blogs, $blog_data ); $current_site->blog_id = $wpdb->insert_id; $blog_id = $wpdb->insert_id; update_user_meta( $site_user->ID, 'source_domain', $domain ); update_user_meta( $site_user->ID, 'primary_blog', $blog_id ); if ( $subdomain_install ) { $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' ); } else { $wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' ); } flush_rewrite_rules(); } // copied from populate_network() private static function add_site_admins( $site_user ) { $site_admins = [ $site_user->user_login ]; $users = get_users( [ 'fields' => [ 'ID', 'user_login' ] ] ); if ( $users ) { foreach ( $users as $user ) { if ( is_super_admin( $user->ID ) && ! in_array( $user->user_login, $site_admins, true ) ) { $site_admins[] = $user->user_login; } } } update_site_option( 'site_admins', $site_admins ); } private static function modify_wp_config( $content ) { $wp_config_path = Utils\locate_wp_config(); $token = "/* That's all, stop editing!"; $config_contents = (string) file_get_contents( $wp_config_path ); if ( false === strpos( $config_contents, $token ) ) { return false; } list( $before, $after ) = explode( $token, $config_contents ); $content = trim( $content ); file_put_contents( $wp_config_path, "{$before}\n\n{$content}\n\n{$token}{$after}" ); return true; } private static function get_clean_basedomain() { /** * @var string $siteurl */ $siteurl = get_option( 'siteurl' ); $domain = (string) preg_replace( '|https?://|', '', $siteurl ); $slash = strpos( $domain, '/' ); if ( false !== $slash ) { $domain = substr( $domain, 0, $slash ); } return $domain; } /** * Displays the WordPress version. * * ## OPTIONS * * [--extra] * : Show extended version information. * * ## EXAMPLES * * # Display the WordPress version * $ wp core version * 4.5.2 * * # Display WordPress version along with other information * $ wp core version --extra * WordPress version: 4.5.2 * Database revision: 36686 * TinyMCE version: 4.310 (4310-20160418) * Package language: en_US * * @when before_wp_load * * @param string[] $args Positional arguments. Unused. * @param array{extra?: bool} $assoc_args Associative arguments. */ public function version( $args = [], $assoc_args = [] ) { $details = self::get_wp_details(); if ( ! Utils\get_flag_value( $assoc_args, 'extra' ) ) { WP_CLI::line( $details['wp_version'] ); return; } $match = []; $found_version = preg_match( '/(\d)(\d+)-/', $details['tinymce_version'], $match ); $human_readable_tiny_mce = $found_version ? "{$match[1]}.{$match[2]}" : ''; echo Utils\mustache_render( self::get_template_path( 'versions.mustache' ), [ 'wp-version' => $details['wp_version'], 'db-version' => $details['wp_db_version'], 'local-package' => empty( $details['wp_local_package'] ) ? 'en_US' : $details['wp_local_package'], 'mce-version' => $human_readable_tiny_mce ? "{$human_readable_tiny_mce} ({$details['tinymce_version']})" : $details['tinymce_version'], ] ); } /** * Gets version information from `wp-includes/version.php`. * * @return array { * @type string $wp_version The WordPress version. * @type int $wp_db_version The WordPress DB revision. * @type string $tinymce_version The TinyMCE version. * @type string $wp_local_package The TinyMCE version. * } */ private static function get_wp_details( $abspath = ABSPATH ) { $versions_path = $abspath . 'wp-includes/version.php'; if ( ! is_readable( $versions_path ) ) { WP_CLI::error( "This does not seem to be a WordPress installation.\n" . 'Pass --path=`path/to/wordpress` or run `wp core download`.' ); } $version_content = (string) file_get_contents( $versions_path, false, null, 6, 2048 ); $vars = [ 'wp_version', 'wp_db_version', 'tinymce_version', 'wp_local_package' ]; $result = []; foreach ( $vars as $var_name ) { $result[ $var_name ] = self::find_var( $var_name, $version_content ); } return $result; } /** * Gets the template path based on installation type. */ private static function get_template_path( $template ) { $command_root = Utils\phar_safe_path( dirname( __DIR__ ) ); $template_path = "{$command_root}/templates/{$template}"; if ( ! file_exists( $template_path ) ) { WP_CLI::error( "Couldn't find {$template}" ); } return $template_path; } /** * Searches for the value assigned to variable `$var_name` in PHP code `$code`. * * This is equivalent to matching the `\$VAR_NAME = ([^;]+)` regular expression and returning * the first match either as a `string` or as an `integer` (depending if it's surrounded by * quotes or not). * * @param string $var_name Variable name to search for. * @param string $code PHP code to search in. * * @return string|null */ private static function find_var( $var_name, $code ) { $start = strpos( $code, '$' . $var_name . ' = ' ); if ( ! $start ) { return null; } $start = $start + strlen( $var_name ) + 3; $end = strpos( $code, ';', $start ); $value = substr( $code, $start, $end - $start ); return trim( $value, " '" ); } /** * Security copy of the core function with Requests - Gets the checksums for the given version of WordPress. * * @param string $version Version string to query. * @param string $locale Locale to query. * @param bool $insecure Whether to retry without certificate validation on TLS handshake failure. * @return string|array String message on failure. An array of checksums on success. */ private static function get_core_checksums( $version, $locale, $insecure ) { $wp_org_api = new WpOrgApi( [ 'insecure' => $insecure ] ); try { /** * @var array|false $checksums */ $checksums = $wp_org_api->get_core_checksums( $version, $locale ); } catch ( Exception $exception ) { return $exception->getMessage(); } if ( false === $checksums ) { return "Checksums not available for WordPress {$version}/{$locale}."; } return $checksums; } /** * Updates WordPress to a newer version. * * Defaults to updating WordPress to the latest version. * * If you see "Error: Another update is currently in progress.", you may * need to run `wp option delete core_updater.lock` after verifying another * update isn't actually running. * * ## OPTIONS * * [<zip>] * : Path to zip file to use, instead of downloading from wordpress.org. * * [--minor] * : Only perform updates for minor releases (e.g. update from WP 4.3 to 4.3.3 instead of 4.4.2). * * [--version=<version>] * : Update to a specific version, instead of to the latest version. Alternatively accepts 'nightly'. * * [--force] * : Update even when installed WP version is greater than the requested version. * * [--locale=<locale>] * : Select which language you want to download. * * [--insecure] * : Retry download without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * * ## EXAMPLES * * # Update WordPress * $ wp core update * Updating to version 4.5.2 (en_US)... * Downloading update from https://downloads.wordpress.org/release/wordpress-4.5.2-no-content.zip... * Unpacking the update... * Cleaning up files... * No files found that need cleaning up * Success: WordPress updated successfully. * * # Update WordPress using zip file. * $ wp core update ../latest.zip * Starting update... * Unpacking the update... * Success: WordPress updated successfully. * * # Update WordPress to 3.1 forcefully * $ wp core update --version=3.1 --force * Updating to version 3.1 (en_US)... * Downloading update from https://wordpress.org/wordpress-3.1.zip... * Unpacking the update... * Warning: Checksums not available for WordPress 3.1/en_US. Please cleanup files manually. * Success: WordPress updated successfully. * * @alias upgrade * * @param array{0?: string} $args Positional arguments. * @param array{minor?: bool, version?: string, force?: bool, locale?: string, insecure?: bool} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { global $wp_version; $update = null; $upgrader = 'WP_CLI\\Core\\CoreUpgrader'; if ( 'trunk' === Utils\get_flag_value( $assoc_args, 'version' ) ) { $assoc_args['version'] = 'nightly'; } if ( ! empty( $args[0] ) ) { // ZIP path or URL is given $upgrader = 'WP_CLI\\Core\\NonDestructiveCoreUpgrader'; $version = Utils\get_flag_value( $assoc_args, 'version' ); $update = (object) [ 'response' => 'upgrade', 'current' => $version, 'download' => $args[0], 'packages' => (object) [ 'partial' => null, 'new_bundled' => null, 'no_content' => null, 'full' => $args[0], ], 'version' => $version, 'locale' => null, ]; } elseif ( empty( $assoc_args['version'] ) ) { // Update to next release wp_version_check(); /** * @var object{updates: array<object{version: string, locale: string}>} $from_api */ $from_api = get_site_transient( 'update_core' ); if ( Utils\get_flag_value( $assoc_args, 'minor' ) ) { foreach ( $from_api->updates as $offer ) { $sem_ver = Utils\get_named_sem_ver( $offer->version, $wp_version ); if ( ! $sem_ver || 'patch' !== $sem_ver ) { continue; } $update = $offer; break; } if ( empty( $update ) ) { WP_CLI::success( 'WordPress is at the latest minor release.' ); return; } } elseif ( ! empty( $from_api->updates ) ) { list( $update ) = $from_api->updates; } } elseif ( Utils\wp_version_compare( $assoc_args['version'], '<' ) || 'nightly' === $assoc_args['version'] || Utils\get_flag_value( $assoc_args, 'force' ) ) { // Specific version is given $version = $assoc_args['version']; /** * @var string $locale */ $locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); $new_package = $this->get_download_url( $version, $locale ); $update = (object) [ 'response' => 'upgrade', 'current' => $assoc_args['version'], 'download' => $new_package, 'packages' => (object) [ 'partial' => null, 'new_bundled' => null, 'no_content' => null, 'full' => $new_package, ], 'version' => $version, 'locale' => $locale, ]; } if ( ! empty( $update ) && ( $update->version !== $wp_version || Utils\get_flag_value( $assoc_args, 'force' ) ) ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; if ( $update->version ) { WP_CLI::log( "Updating to version {$update->version} ({$update->locale})..." ); } else { WP_CLI::log( 'Starting update...' ); } $from_version = $wp_version; $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); $GLOBALS['wpcli_core_update_obj'] = $update; /** * @var \WP_CLI\Core\CoreUpgrader $wp_upgrader */ $wp_upgrader = Utils\get_upgrader( $upgrader, $insecure ); $result = $wp_upgrader->upgrade( $update ); unset( $GLOBALS['wpcli_core_update_obj'] ); if ( is_wp_error( $result ) ) { $message = WP_CLI::error_to_string( $result ); if ( 'up_to_date' !== $result->get_error_code() ) { WP_CLI::error( $message ); } else { WP_CLI::success( $message ); } } else { $to_version = ''; if ( file_exists( ABSPATH . 'wp-includes/version.php' ) ) { $wp_details = self::get_wp_details(); $to_version = $wp_details['wp_version']; } /** * @var string $locale */ $locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); $this->cleanup_extra_files( $from_version, $to_version, $locale, $insecure ); WP_CLI::success( 'WordPress updated successfully.' ); } } else { WP_CLI::success( 'WordPress is up to date.' ); } } /** * Runs the WordPress database update procedure. * * ## OPTIONS * * [--network] * : Update databases for all sites on a network * * [--dry-run] * : Compare database versions without performing the update. * * ## EXAMPLES * * # Update the WordPress database. * $ wp core update-db * Success: WordPress database upgraded successfully from db version 36686 to 35700. * * # Update databases for all sites on a network. * $ wp core update-db --network * WordPress database upgraded successfully from db version 35700 to 29630 on example.com/ * Success: WordPress database upgraded on 123/123 sites. * * @subcommand update-db * * @param string[] $args Positional arguments. Unused. * @param array{network?: bool, 'dry-run'?: bool} $assoc_args Associative arguments. */ public function update_db( $args, $assoc_args ) { global $wpdb, $wp_db_version, $wp_current_db_version; $network = Utils\get_flag_value( $assoc_args, 'network' ); if ( $network && ! is_multisite() ) { WP_CLI::error( 'This is not a multisite installation.' ); } $dry_run = Utils\get_flag_value( $assoc_args, 'dry-run' ); if ( $dry_run ) { WP_CLI::log( 'Performing a dry run, with no database modification.' ); } if ( $network ) { $iterator_args = [ 'table' => $wpdb->blogs, 'where' => [ 'spam' => 0, 'deleted' => 0, 'archived' => 0, ], ]; $it = new TableIterator( $iterator_args ); $success = 0; $total = 0; $site_ids = []; /** * @var object{site_id: int, domain: string, path: string} $blog */ foreach ( $it as $blog ) { ++$total; $site_ids[] = $blog->site_id; $url = $blog->domain . $blog->path; $cmd = "--url={$url} core update-db"; if ( $dry_run ) { $cmd .= ' --dry-run'; } /** * @var object{stdout: string, stderr: string, return_code: int} $process */ $process = WP_CLI::runcommand( $cmd, [ 'return' => 'all', 'exit_error' => false, ] ); if ( 0 === (int) $process->return_code ) { // See if we can parse the stdout if ( preg_match( '#Success: (.+)#', $process->stdout, $matches ) ) { $message = rtrim( $matches[1], '.' ); $message = "{$message} on {$url}"; } else { $message = "Database upgraded successfully on {$url}"; } WP_CLI::log( $message ); ++$success; } else { WP_CLI::warning( "Database failed to upgrade on {$url}" ); } } if ( ! $dry_run && $total && $success === $total ) { foreach ( array_unique( $site_ids ) as $site_id ) { update_metadata( 'site', $site_id, 'wpmu_upgrade_site', $wp_db_version ); } } WP_CLI::success( "WordPress database upgraded on {$success}/{$total} sites." ); } else { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; /** * @var string $wp_current_db_version */ // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here. $wp_current_db_version = __get_option( 'db_version' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here. $wp_current_db_version = (int) $wp_current_db_version; if ( $wp_db_version !== $wp_current_db_version ) { if ( $dry_run ) { WP_CLI::success( "WordPress database will be upgraded from db version {$wp_current_db_version} to {$wp_db_version}." ); } else { // WP upgrade isn't too fussy about generating MySQL warnings such as "Duplicate key name" during an upgrade so suppress. $wpdb->suppress_errors(); // WP upgrade expects `$_SERVER['HTTP_HOST']` to be set in `wp_guess_url()`, otherwise get PHP notice. if ( ! isset( $_SERVER['HTTP_HOST'] ) ) { $_SERVER['HTTP_HOST'] = 'example.com'; } wp_upgrade(); WP_CLI::success( "WordPress database upgraded successfully from db version {$wp_current_db_version} to {$wp_db_version}." ); } } else { WP_CLI::success( "WordPress database already at latest db version {$wp_db_version}." ); } } } /** * Gets download url based on version, locale and desired file type. * * @param $version * @param string $locale * @param string $file_type * @return string */ private function get_download_url( $version, $locale = 'en_US', $file_type = 'zip' ) { if ( 'nightly' === $version ) { if ( 'zip' === $file_type ) { return 'https://wordpress.org/nightly-builds/wordpress-latest.zip'; } else { WP_CLI::error( 'Nightly builds are only available in .zip format.' ); } } $locale_subdomain = 'en_US' === $locale ? '' : substr( $locale, 0, 2 ) . '.'; $locale_suffix = 'en_US' === $locale ? '' : "-{$locale}"; // Match 6.7.0 but not 6.0 if ( substr_count( $version, '.' ) > 1 && substr( $version, -2 ) === '.0' ) { $version = substr( $version, 0, -2 ); } return "https://{$locale_subdomain}wordpress.org/wordpress-{$version}{$locale_suffix}.{$file_type}"; } /** * Returns update information. * * @param array $assoc_args Associative array of arguments. * @return array List of available updates , or an empty array if no updates are available. */ private function get_updates( $assoc_args ) { $force_check = Utils\get_flag_value( $assoc_args, 'force-check' ); wp_version_check( [], $force_check ); /** * @var object{updates: array<object{version: string, locale: string, packages: object{partial?: string, full: string}}>}|false $from_api */ $from_api = get_site_transient( 'update_core' ); if ( ! $from_api ) { return []; } $compare_version = str_replace( '-src', '', $GLOBALS['wp_version'] ); $updates = [ 'major' => false, 'minor' => false, ]; foreach ( $from_api->updates as $offer ) { $update_type = Utils\get_named_sem_ver( $offer->version, $compare_version ); if ( ! $update_type ) { continue; } // WordPress follow its own versioning which is roughly equivalent to semver if ( 'minor' === $update_type ) { $update_type = 'major'; } elseif ( 'patch' === $update_type ) { $update_type = 'minor'; } if ( ! empty( $updates[ $update_type ] ) && ! Comparator::greaterThan( $offer->version, $updates[ $update_type ]['version'] ) ) { continue; } $updates[ $update_type ] = [ 'version' => $offer->version, 'update_type' => $update_type, 'package_url' => ! empty( $offer->packages->partial ) ? $offer->packages->partial : $offer->packages->full, ]; } foreach ( $updates as $type => $value ) { if ( empty( $value ) ) { unset( $updates[ $type ] ); } } foreach ( [ 'major', 'minor' ] as $type ) { if ( true === Utils\get_flag_value( $assoc_args, $type ) ) { return ! empty( $updates[ $type ] ) ? [ $updates[ $type ] ] : []; } } return array_values( $updates ); } /** * Clean up extra files. * * @param string $version_from Starting version that the installation was updated from. * @param string $version_to Target version that the installation is updated to. * @param string $locale Locale of the installation. * @param bool $insecure Whether to retry without certificate validation on TLS handshake failure. */ private function cleanup_extra_files( $version_from, $version_to, $locale, $insecure ) { if ( ! $version_from || ! $version_to ) { WP_CLI::warning( 'Failed to find WordPress version. Please cleanup files manually.' ); return; } $old_checksums = self::get_core_checksums( $version_from, $locale ?: 'en_US', $insecure ); if ( ! is_array( $old_checksums ) ) { WP_CLI::warning( "{$old_checksums} Please cleanup files manually." ); return; } $new_checksums = self::get_core_checksums( $version_to, $locale ?: 'en_US', $insecure ); if ( ! is_array( $new_checksums ) ) { WP_CLI::warning( "{$new_checksums} Please cleanup files manually." ); return; } // Compare the files from the old version and the new version in a case-insensitive manner, // to prevent files being incorrectly deleted on systems with case-insensitive filesystems // when core changes the case of filenames. // The main logic for this was taken from the Joomla project and adapted for WP. // See: https://github.com/joomla/joomla-cms/blob/bb5368c7ef9c20270e6e9fcc4b364cd0849082a5/administrator/components/com_admin/script.php#L8158 $old_filepaths = array_keys( $old_checksums ); $new_filepaths = array_keys( $new_checksums ); $new_filepaths = array_combine( array_map( 'strtolower', $new_filepaths ), $new_filepaths ); $old_filepaths_to_check = array_diff( $old_filepaths, $new_filepaths ); foreach ( $old_filepaths_to_check as $old_filepath_to_check ) { $old_realpath = realpath( ABSPATH . $old_filepath_to_check ); // On Unix without incorrectly cased file. if ( false === $old_realpath ) { continue; } $lowercase_old_filepath_to_check = strtolower( $old_filepath_to_check ); if ( ! array_key_exists( $lowercase_old_filepath_to_check, $new_filepaths ) ) { $files_to_remove[] = $old_filepath_to_check; continue; } // We are now left with only the files that are similar from old to new except for their case. $old_basename = basename( $old_realpath ); $new_filepath = $new_filepaths[ $lowercase_old_filepath_to_check ]; $expected_basename = basename( $new_filepath ); $new_realpath = (string) realpath( ABSPATH . $new_filepath ); $new_basename = basename( $new_realpath ); // On Windows or Unix with only the incorrectly cased file. if ( $new_basename !== $expected_basename ) { WP_CLI::debug( "Renaming file '{$old_filepath_to_check}' => '{$new_filepath}'", 'core' ); rename( ABSPATH . $old_filepath_to_check, ABSPATH . $old_filepath_to_check . '.tmp' ); rename( ABSPATH . $old_filepath_to_check . '.tmp', ABSPATH . $new_filepath ); continue; } // There might still be an incorrectly cased file on other OS than Windows. if ( basename( $old_filepath_to_check ) === $old_basename ) { // Check if case-insensitive file system, eg on OSX. if ( fileinode( $old_realpath ) === fileinode( $new_realpath ) ) { $files = scandir( dirname( $new_realpath ) ) ?: []; // Check deeper because even realpath or glob might not return the actual case. if ( ! in_array( $expected_basename, $files, true ) ) { WP_CLI::debug( "Renaming file '{$old_filepath_to_check}' => '{$new_filepath}'", 'core' ); rename( ABSPATH . $old_filepath_to_check, ABSPATH . $old_filepath_to_check . '.tmp' ); rename( ABSPATH . $old_filepath_to_check . '.tmp', ABSPATH . $new_filepath ); } } else { // On Unix with both files: Delete the incorrectly cased file. $files_to_remove[] = $old_filepath_to_check; } } } if ( ! empty( $files_to_remove ) ) { WP_CLI::log( 'Cleaning up files...' ); $count = 0; foreach ( $files_to_remove as $file ) { // wp-content should be considered user data if ( 0 === stripos( $file, 'wp-content' ) ) { continue; } if ( file_exists( ABSPATH . $file ) ) { unlink( ABSPATH . $file ); WP_CLI::log( "File removed: {$file}" ); ++$count; } } if ( $count ) { WP_CLI::log( number_format( $count ) . ' files cleaned up.' ); } else { WP_CLI::log( 'No files found that need cleaning up.' ); } } } private static function strip_content_dir( $zip_file ) { $new_zip_file = Utils\get_temp_dir() . uniqid( 'wp_' ) . '.zip'; register_shutdown_function( function () use ( $new_zip_file ) { if ( file_exists( $new_zip_file ) ) { unlink( $new_zip_file ); } } ); // Duplicate file to avoid modifying the original, which could be cache. if ( ! copy( $zip_file, $new_zip_file ) ) { WP_CLI::error( 'Failed to copy ZIP file.' ); } $zip = new ZipArchive(); $res = $zip->open( $new_zip_file ); if ( true === $res ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase for ( $i = 0; $i < $zip->numFiles; $i++ ) { $info = $zip->statIndex( $i ); if ( ! $info ) { continue; } // Strip all files in wp-content/themes and wp-content/plugins // but leave the directories and index.php files intact. if ( in_array( $info['name'], array( 'wordpress/wp-content/plugins/', 'wordpress/wp-content/plugins/index.php', 'wordpress/wp-content/themes/', 'wordpress/wp-content/themes/index.php', ), true ) ) { continue; } if ( 0 === stripos( $info['name'], 'wordpress/wp-content/themes/' ) || 0 === stripos( $info['name'], 'wordpress/wp-content/plugins/' ) ) { $zip->deleteIndex( $i ); } } $zip->close(); return $new_zip_file; } else { WP_CLI::error( 'ZipArchive failed to open ZIP file.' ); } } }
Close