-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add/sqlite import export support #259
Changes from 16 commits
effeac9
648f5c0
6543dd9
0c81605
05714cb
f6b2da6
963fc04
c23bd71
a3e359b
b10aa9e
1d36969
d33bb66
74e4008
73fb1d3
377a450
46863b8
2753c79
9085b5e
69dfb06
a9b61e0
241b89c
f9affee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,23 +75,23 @@ Feature: Query the database with WordPress' MySQL config | |
Scenario: MySQL defaults are available as appropriate with --defaults flag | ||
Given a WP install | ||
|
||
When I try `wp db query --defaults --debug` | ||
When I try `"select 1" | wp db query --defaults --debug` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the context of this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test command expects STDIN, none was given so it would cause the command to freeze indefinitely and the test would be stuck (at least locally). |
||
Then STDERR should contain: | ||
""" | ||
Debug (db): Running shell command: /usr/bin/env mysql --no-auto-rehash | ||
""" | ||
|
||
When I try `wp db query --debug` | ||
When I try `"select 1" | wp db query --debug` | ||
Then STDERR should contain: | ||
""" | ||
Debug (db): Running shell command: /usr/bin/env mysql --no-defaults --no-auto-rehash | ||
""" | ||
|
||
When I try `wp db query --no-defaults --debug` | ||
When I try `"select 1" | wp db query --no-defaults --debug` | ||
Then STDERR should contain: | ||
""" | ||
Debug (db): Running shell command: /usr/bin/env mysql --no-defaults --no-auto-rehash | ||
""" | ||
""" | ||
|
||
Scenario: SQL modes do not include any of the modes incompatible with WordPress | ||
Given a WP install | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
<?php | ||
|
||
use WP_CLI\DB\SQLite\Export; | ||
use WP_CLI\DB\SQLite\Import; | ||
use WP_CLI\Formatter; | ||
use WP_CLI\Utils; | ||
|
||
|
@@ -596,6 +598,7 @@ public function export( $args, $assoc_args ) { | |
$result_file = sprintf( '%s-%s-%s.sql', DB_NAME, date( 'Y-m-d' ), $hash ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date | ||
|
||
} | ||
|
||
$stdout = ( '-' === $result_file ); | ||
$porcelain = Utils\get_flag_value( $assoc_args, 'porcelain' ); | ||
|
||
|
@@ -604,6 +607,13 @@ public function export( $args, $assoc_args ) { | |
WP_CLI::error( 'Porcelain is not allowed when output mode is STDOUT.' ); | ||
} | ||
|
||
// Check if SQLite is enabled and use it if it is. | ||
if ( Export::get_sqlite_plugin_version() ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we check for a minimal supported version of the SQLite plugin and fail with the error if it's older? Or do we rely on the logic inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment we check the version of the SQLite plugin when we load the dependencies. We can do this here as well. I assume you still want it to trigger the same error right? |
||
$export = new Export(); | ||
$export->run( $result_file, $assoc_args ); | ||
return; | ||
} | ||
|
||
if ( ! $stdout ) { | ||
$assoc_args['result-file'] = $result_file; | ||
} | ||
|
@@ -762,6 +772,13 @@ public function import( $args, $assoc_args ) { | |
$result_file = sprintf( '%s.sql', DB_NAME ); | ||
} | ||
|
||
// Check if SQLite is enabled and use it if it is. | ||
if ( Import::get_sqlite_plugin_version() ) { | ||
$importer = new Import(); | ||
$importer->run( $result_file, $assoc_args ); | ||
return; | ||
} | ||
|
||
// Process options to MySQL. | ||
$mysql_args = array_merge( | ||
[ 'database' => DB_NAME ], | ||
|
@@ -842,7 +859,6 @@ public function import( $args, $assoc_args ) { | |
* # Export only tables for a single site | ||
* $ wp db export --tables=$(wp db tables --url=sub.example.com --format=csv) | ||
* Success: Exported to wordpress_dbase.sql | ||
* | ||
* @when after_wp_load | ||
*/ | ||
public function tables( $args, $assoc_args ) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
<?php | ||
namespace WP_CLI\DB\SQLite; | ||
|
||
use WP_CLI; | ||
|
||
class Base { | ||
|
||
protected $unsupported_arguments = []; | ||
|
||
/** | ||
* Get the version of the SQLite integration plugin if it is installed | ||
* and activated. | ||
* | ||
* @return false|string The version of the SQLite integration plugin or false if not found/activated. | ||
*/ | ||
public static function get_sqlite_plugin_version() { | ||
// Check if there is a db.php file in the wp-content directory. | ||
if ( ! file_exists( ABSPATH . '/wp-content/db.php' ) ) { | ||
return false; | ||
} | ||
|
||
// If the file is found, we need to check that it is the sqlite integration plugin. | ||
$plugin_file = file_get_contents( ABSPATH . '/wp-content/db.php' ); | ||
if ( ! preg_match( '/define\( \'SQLITE_DB_DROPIN_VERSION\', \'([0-9.]+)\' \)/', $plugin_file ) ) { | ||
return false; | ||
} | ||
|
||
$plugin_path = self::get_plugin_directory(); | ||
if ( ! $plugin_path ) { | ||
return false; | ||
} | ||
|
||
// Try to get the version number from readme.txt | ||
$plugin_file = file_get_contents( $plugin_path . '/readme.txt' ); | ||
|
||
preg_match( '/^Stable tag:\s*?(.+)$/m', $plugin_file, $matches ); | ||
|
||
return isset( $matches[1] ) ? trim( $matches[1] ) : false; | ||
} | ||
|
||
/** | ||
* Find the directory where the SQLite integration plugin is installed. | ||
* | ||
* @return string|null The directory where the SQLite integration plugin is installed or null if not found. | ||
*/ | ||
protected static function get_plugin_directory() { | ||
$plugin_folders = [ | ||
ABSPATH . '/wp-content/plugins/sqlite-database-integration', | ||
ABSPATH . '/wp-content/mu-plugins/sqlite-database-integration', | ||
]; | ||
|
||
foreach ( $plugin_folders as $folder ) { | ||
if ( file_exists( $folder ) && is_dir( $folder ) ) { | ||
return $folder; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* Load the necessary classes from the SQLite integration plugin. | ||
* | ||
* @return void | ||
* @throws WP_CLI\ExitException | ||
*/ | ||
protected function load_dependencies() { | ||
$plugin_directory = self::get_plugin_directory(); | ||
if ( ! $plugin_directory ) { | ||
WP_CLI::error( 'Could not locate the SQLite integration plugin.' ); | ||
} | ||
|
||
$sqlite_plugin_version = self::get_sqlite_plugin_version(); | ||
if ( ! $sqlite_plugin_version ) { | ||
WP_CLI::error( 'Could not determine the version of the SQLite integration plugin.' ); | ||
} | ||
|
||
if ( version_compare( $sqlite_plugin_version, '2.1.11', '<' ) ) { | ||
WP_CLI::error( 'The SQLite integration plugin must be version 2.1.11 or higher.' ); | ||
} | ||
|
||
// Load the translator class from the plugin. | ||
if ( ! defined( 'SQLITE_DB_DROPIN_VERSION' ) ) { | ||
define( 'SQLITE_DB_DROPIN_VERSION', $sqlite_plugin_version ); // phpcs:ignore | ||
} | ||
|
||
# WordPress is not loaded during the execution of the export and import commands. | ||
# The SQLite database integration plugin uses do_action and apply_filters to hook | ||
# into the WordPress core. To prevent a fatal error, we can define these functions | ||
# as no-op functions. | ||
require_once __DIR__ . '/noop.php'; | ||
|
||
// We also need to selectively load the necessary classes from the plugin. | ||
require_once $plugin_directory . '/php-polyfills.php'; | ||
require_once $plugin_directory . '/constants.php'; | ||
require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-lexer.php'; | ||
require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-query-rewriter.php'; | ||
require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-translator.php'; | ||
require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-token.php'; | ||
require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; | ||
} | ||
|
||
/** | ||
* Check if the arguments passed to the command are supported. | ||
* | ||
* @param $args | ||
* | ||
* @return void | ||
* @throws WP_CLI\ExitException | ||
*/ | ||
protected function check_arguments( $args ) { | ||
if ( array_intersect_key( $args, array_flip( $this->unsupported_arguments ) ) ) { | ||
WP_CLI::error( | ||
sprintf( | ||
'The following arguments are not supported by SQLite exports: %s', | ||
implode( ', ', $this->unsupported_arguments ) | ||
) | ||
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch and fix. I see this test was there for 5 years. How did it even work before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it depends on the environment. We both experienced this issue locally but the CI seems to be fine with it.