Skip to content

Commit

Permalink
backport more changes
Browse files Browse the repository at this point in the history
  • Loading branch information
aristath committed Apr 5, 2023
1 parent 652ee48 commit c8acf14
Show file tree
Hide file tree
Showing 15 changed files with 1,339 additions and 409 deletions.
339 changes: 339 additions & 0 deletions modules/database/sqlite/LICENSE

Large diffs are not rendered by default.

213 changes: 66 additions & 147 deletions modules/database/sqlite/activate.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,66 @@
<?php
/**
* Actions to run when the module gets activated.
* Handle the SQLite activation.
*
* @since 1.8.0
* @package performance-lab
* @since 1.0.0
* @package wp-sqlite-integration
*/

/**
* Copies the db.php file in wp-content and reloads the page.
* Redirect to the plugin's admin screen on activation.
*
* @since 1.8.0
* @since 1.0.0
*
* @param string $plugin The plugin basename.
*/
function sqlite_plugin_activation_redirect( $plugin ) {
if ( plugin_basename( SQLITE_MAIN_FILE ) === $plugin ) {
wp_redirect( admin_url( 'options-general.php?page=sqlite-integration' ) );
exit;
}
}
add_action( 'activated_plugin', 'sqlite_plugin_activation_redirect' );

/**
* Check the URL to ensure we're on the plugin page,
* the user has clicked the button to install SQLite,
* and the nonce is valid.
* If the above conditions are met, run the sqlite_plugin_copy_db_file() function,
* and redirect to the install screen.
*
* @since 1.0.0
*/
function sqlite_activation() {
global $current_screen;
if ( isset( $current_screen->base ) && 'settings_page_sqlite-integration' === $current_screen->base ) {
return;
}
if ( isset( $_GET['confirm-install'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'sqlite-install' ) ) {
sqlite_plugin_copy_db_file(); // phpcs:ignore PHPCompatibility.Extensions.RemovedExtensions
// WordPress will automatically redirect to the install screen here.
wp_redirect( admin_url() );
exit;
}
}
add_action( 'admin_init', 'sqlite_activation' );

// Flush the cache at the last moment before the redirect.
add_filter(
'x_redirect_by',
function ( $result ) {
wp_cache_flush();
return $result;
},
PHP_INT_MAX,
1
);

/**
* Add the db.php file in wp-content.
*
* When the plugin gets merged in wp-core, this is not to be ported.
*/
return function() {
function sqlite_plugin_copy_db_file() {
// Bail early if the SQLite3 class does not exist.
if ( ! class_exists( 'SQLite3' ) ) {
return;
Expand All @@ -21,7 +70,7 @@

// Place database drop-in if not present yet, except in case there is
// another database drop-in present already.
if ( ! defined( 'PERFLAB_SQLITE_DB_DROPIN_VERSION' ) && ! file_exists( $destination ) ) {
if ( ! defined( 'SQLITE_DB_DROPIN_VERSION' ) && ! file_exists( $destination ) ) {
// Init the filesystem to allow copying the file.
global $wp_filesystem;

Expand All @@ -32,148 +81,18 @@

// Get the db.copy.php file contents, replace placeholders and write it to the destination.
$file_contents = str_replace(
'{SQLITE_IMPLEMENTATION_FOLDER_PATH}',
__DIR__,
file_get_contents( __DIR__ . '/db.copy.php' )
array(
'{SQLITE_IMPLEMENTATION_FOLDER_PATH}',
'{SQLITE_PLUGIN}',
),
array(
__DIR__,
str_replace( WP_PLUGIN_DIR . '/', '', SQLITE_MAIN_FILE ),
),
file_get_contents( __DIR__ . '/db.copy' )
);

$wp_filesystem->put_contents( $destination, $file_contents );
}
}

// Do not automatically set up SQLite DB on a multisite as that is notably
// more complex. Potentially it can be added in the future.
if ( is_multisite() ) {
return;
}

// As an extra safety check, bail if the current user cannot update
// (or install) WordPress core.
if ( ! current_user_can( 'update_core' ) ) {
return;
}

// Otherwise install WordPress in the SQLite database before the redirect,
// so that the user does not end up on the WordPress installation screen
// but rather remains in the Performance Lab modules screen.
add_filter(
'wp_redirect',
function( $redirect_location ) {
if ( ! defined( 'DB_ENGINE' ) ) {
define( 'DB_ENGINE', 'sqlite' );
}
require_once __DIR__ . '/constants.php';

// If the SQLite DB already exists, simply ensure the module is
// active there.
if ( file_exists( FQDB ) ) {
require_once __DIR__ . '/wp-includes/sqlite/db.php';
wp_set_wpdb_vars();
global $wpdb;
$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", PERFLAB_MODULES_SETTING ) );
if ( is_object( $row ) ) {
$value = maybe_unserialize( $row->option_value );
if ( is_array( $value ) && ( ! isset( $value['database/sqlite'] ) || ! $value['database/sqlite']['enabled'] ) ) {
$value['database/sqlite'] = array( 'enabled' => true );
$wpdb->update( $wpdb->options, array( 'option_value' => maybe_serialize( $value ) ), array( 'option_name' => PERFLAB_MODULES_SETTING ) );
}
}
return $redirect_location;
}

// Get current basic setup data to install WordPress in the new DB.
$blog_title = get_bloginfo( 'name' );
$is_public = (bool) get_option( 'blog_public' );
$language = get_option( 'WPLANG' );
$admin_email = get_option( 'admin_email' );
$admin_user = get_user_by( 'email', $admin_email );
if ( ! $admin_user ) {
$admin_user = wp_get_current_user();
}

// Look up the data for the current user (in case they're not the
// admin email user). Additionally, attempt to keep them
// logged-in by retaining their current session. Depending on the
// site configuration, this is not 100% reliable as sites may store
// session tokens outside of user meta. However that does not lead
// to any problem, the user would simply be required to sign in
// again.
$current_user = wp_get_current_user();
$current_user_sessions = get_user_meta( $current_user->ID, 'session_tokens', true );

// Get current data to keep the Performance Lab plugin and relevant
// modules active in the new DB.
$active_plugins_option = array( plugin_basename( PERFLAB_MAIN_FILE ) );
$active_modules_option = get_option( PERFLAB_MODULES_SETTING, array() );

// Load and set up SQLite database.
require_once __DIR__ . '/wp-includes/sqlite/db.php';
wp_set_wpdb_vars();

// Load WordPress installation API functions.
require_once ABSPATH . 'wp-admin/includes/upgrade.php';

// Install WordPress in the SQLite database with the same base
// configuration as the MySQL database.
// Since $admin_user->user_pass is already hashed, add a filter to
// ensure it is inserted into the database like that, instead of
// being re-hashed.
$unhash_user_pass = function( $data, $update, $user_id, $userdata ) use ( $admin_user, $current_user ) {
// Double check this is actually the already hashed password,
// to prevent any chance of accidentally putting another
// password into the database which would then be plain text.
if (
! empty( $userdata['user_pass'] )
&& (
$userdata['user_pass'] === $admin_user->user_pass
|| $userdata['user_pass'] === $current_user->user_pass
)
) {
$data['user_pass'] = $userdata['user_pass'];
}
return $data;
};
add_filter( 'wp_pre_insert_user_data', $unhash_user_pass, 10, 4 );
wp_install( $blog_title, $admin_user->user_login, $admin_user->user_email, $is_public, '', $admin_user->user_pass, $language );
// If the current user is not the admin user, create an account for that user too.
if ( $current_user->user_login !== $admin_user->user_login ) {
wp_create_user( $current_user->user_login, $current_user->user_pass, $current_user->user_email );
}
remove_filter( 'wp_pre_insert_user_data', $unhash_user_pass );

// If the admin email was originally not attached to any user
// (e.g. when the original admin email user was deleted), reset
// the option to the original admin email again (by default
// `wp_install()` will set it to the same email as the initial
// admin user email).
if ( 0 !== strcasecmp( $admin_user->user_email, $admin_email ) ) {
update_option( 'admin_email', $admin_email );
}

// If user sessions are found, migrate them over so that the
// current user remains logged in.
if ( $current_user_sessions ) {
$session_user = get_user_by( 'login', $current_user->user_login );
if ( $session_user ) {
update_user_meta( $session_user->ID, 'session_tokens', $current_user_sessions );
}
}

// Activate the Performance Lab plugin and its modules.
// Use direct database query for Performance Lab modules to
// prevent module activation logic from firing again.
update_option( 'active_plugins', $active_plugins_option );
global $wpdb;
$wpdb->insert(
$wpdb->options,
array(
'option_name' => PERFLAB_MODULES_SETTING,
'option_value' => maybe_serialize( $active_modules_option ),
'autoload' => 'yes',
)
);

return $redirect_location;
}
);
};
}
73 changes: 73 additions & 0 deletions modules/database/sqlite/admin-notices.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/**
* Functions to add admin notices if necessary.
*
* @since 1.0.0
* @package wp-sqlite-integration
*/

/**
* Add admin notices.
*
* When the plugin gets merged in wp-core, this is not to be ported.
*/
function sqlite_plugin_admin_notice() {

// Don't print notices in the plugin's admin screen.
global $current_screen;
if ( isset( $current_screen->base ) && 'settings_page_sqlite-integration' === $current_screen->base ) {
return;
}

// If SQLite is not detected, bail early.
if ( ! class_exists( 'SQLite3' ) ) {
printf(
'<div class="notice notice-error"><p>%s</p></div>',
esc_html__( 'The SQLite Integration plugin is active, but the SQLite3 class is missing from your server. Please make sure that SQLite is enabled in your PHP installation.', 'performance-lab' )
);
return;
}

/*
* If the SQLITE_DB_DROPIN_VERSION constant is not defined
* but there's a db.php file in the wp-content directory, then the module can't be activated.
* The module should not have been activated in the first place
* (there's a check in the can-load.php file), but this is a fallback check.
*/
if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && ! defined( 'SQLITE_DB_DROPIN_VERSION' ) ) {
printf(
'<div class="notice notice-error"><p>%s</p></div>',
sprintf(
/* translators: 1: SQLITE_DB_DROPIN_VERSION constant, 2: db.php drop-in path */
__( 'The SQLite Integration module is active, but the %1$s constant is missing. It appears you already have another %2$s file present on your site. ', 'performance-lab' ),
'<code>SQLITE_DB_DROPIN_VERSION</code>',
'<code>' . esc_html( basename( WP_CONTENT_DIR ) ) . '/db.php</code>'
)
);

return;
}

if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
return;
}

if ( ! wp_is_writable( WP_CONTENT_DIR ) ) {
printf(
'<div class="notice notice-error"><p>%s</p></div>',
esc_html__( 'The SQLite Integration plugin is active, but the wp-content/db.php file is missing and the wp-content directory is not writable. Please ensure the wp-content folder is writable, then deactivate the plugin and try again.', 'performance-lab' )
);
return;
}
// The dropin db.php is missing.
printf(
'<div class="notice notice-error"><p>%s</p></div>',
sprintf(
/* translators: 1: db.php drop-in path, 2: Admin URL to deactivate the module */
__( 'The SQLite Integration plugin is active, but the %1$s file is missing. Please <a href="%2$s">deactivate the plugin</a> and re-activate it to try again.', 'performance-lab' ),
'<code>' . esc_html( basename( WP_CONTENT_DIR ) ) . '/db.php</code>',
esc_url( admin_url( 'plugins.php' ) )
)
);
}
add_action( 'admin_notices', 'sqlite_plugin_admin_notice' ); // Add the admin notices.
Loading

0 comments on commit c8acf14

Please sign in to comment.