Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactoring
  • Loading branch information
jeroenpf committed Jul 25, 2024
commit 377a4508d2f59f8f8edc5ff65b30f171257f70ac
27 changes: 23 additions & 4 deletions src/SQLite/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ class Base {
protected $unsupported_arguments = [];

/**
* Tries to determine if the current site is using SQL by checking
* for an active sqlite integration plugin.
* @return false|void
* 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 ) ) {
Expand All @@ -28,6 +30,7 @@ public static function get_sqlite_plugin_version() {
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 );
Expand All @@ -36,7 +39,9 @@ public static function get_sqlite_plugin_version() {
}

/**
* @return string|null
* 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 = [
Expand All @@ -53,6 +58,12 @@ protected static function get_plugin_directory() {
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 ) {
Expand Down Expand Up @@ -89,6 +100,14 @@ protected function load_dependencies() {
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(
Expand Down
164 changes: 133 additions & 31 deletions src/SQLite/Export.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

class Export extends Base {

/**
* List of arguments that are not supported by the export command.
* @var string[]
*/
protected $unsupported_arguments = [
'fields',
'include-tablespaces',
Expand All @@ -16,6 +20,15 @@ class Export extends Base {
'dbpass',
];

protected $translator;
protected $args = array();
protected $is_stdout = false;

public function __construct() {
$this->load_dependencies();
$this->translator = new WP_SQLite_Translator();
}

/**
* Run the export command.
*
Expand All @@ -26,26 +39,74 @@ class Export extends Base {
* @throws Exception
*/
public function run( $result_file, $args ) {

$this->args = $args;
$this->check_arguments( $args );
$this->load_dependencies();
$is_stdout = '-' === $result_file;

$exclude_tables = isset( $args['exclude_tables'] ) ? explode( ',', $args['exclude_tables'] ) : [];
$exclude_tables = array_merge(
$exclude_tables,
[
'_mysql_data_types_cache',
'sqlite_master',
'sqlite_sequence',
]
);
$handle = $this->open_output_stream( $result_file );

$include_tables = isset( $args['tables'] ) ? explode( ',', $args['tables'] ) : [];
$this->write_sql_statements( $handle );
$this->close_output_stream( $handle );

$translator = new WP_SQLite_Translator();
$handle = $is_stdout ? fopen( 'php://stdout', 'w' ) : fopen( $result_file, 'w' );
$this->display_result_message( $result_file );
}

/**
* Get output stream for the export.
*
* @param $result_file
*
* @return false|resource
* @throws WP_CLI\ExitException
*/
protected function open_output_stream( $result_file ) {
$this->is_stdout = '-' === $result_file;
$handle = $this->is_stdout ? fopen( 'php://stdout', 'w' ) : fopen( $result_file, 'w' );
if ( ! $handle ) {
WP_CLI::error( "Unable to open file: $result_file" );
}
return $handle;
}

/**
* Close the output stream.
*
* @param $handle
*
* @return void
* @throws WP_CLI\ExitException
*/
protected function close_output_stream( $handle ) {
if ( ! fclose( $handle ) ) {
WP_CLI::error( 'Error closing output stream.' );
}
}

/**
* Write SQL statements to the output stream.
*
* @param resource $handle The output stream.
*
* @return void
* @throws Exception
*/
protected function write_sql_statements( $handle ) {
foreach ( $this->get_sql_statements() as $statement ) {
fwrite( $handle, $statement . PHP_EOL );
}

fwrite( $handle, sprintf( '-- Dump completed on %s', gmdate( 'c' ) ) );
}

/**
* Get SQL statements for the dump.
*
* @return \Generator
* @throws Exception
*/
protected function get_sql_statements() {
$include_tables = $this->get_include_tables();
$exclude_tables = $this->get_exclude_tables();
$translator = $this->translator;
foreach ( $translator->query( 'SHOW TABLES' ) as $table ) {

// Skip tables that are not in the include_tables list if the list is defined
Expand All @@ -58,33 +119,36 @@ public function run( $result_file, $args ) {
continue;
}

fwrite( $handle, 'DROP TABLE IF EXISTS `' . $table->name . "`;\n" );
fwrite( $handle, $this->get_create_statement( $table, $translator ) . "\n" );
yield sprintf( 'DROP TABLE IF EXISTS `%s`;', $table->name );
yield $this->get_create_statement( $table, $translator );

foreach ( $this->get_insert_statements( $table, $translator->get_pdo() ) as $insert_statement ) {
fwrite( $handle, $insert_statement . "\n" );
yield $insert_statement;
}
}

fwrite( $handle, sprintf( '-- Dump completed on %s', gmdate( 'c' ) ) );
fclose( $handle );

if ( $is_stdout ) {
return;
}

if ( isset( $args['porcelain'] ) ) {
WP_CLI::line( $result_file );
} else {
WP_CLI::success( 'Export complete. File written to ' . $result_file );
}
}

/**
* Get the CREATE TABLE statement for a table.
*
* @param $table
* @param $translator
*
* @return mixed
*/
protected function get_create_statement( $table, $translator ) {
$create = $translator->query( 'SHOW CREATE TABLE ' . $table->name );
return $create[0]->{'Create Table'};
}

/**
* Get the INSERT statements for a table.
*
* @param $table
* @param $pdo
*
* @return \Generator
*/
protected function get_insert_statements( $table, $pdo ) {
$stmt = $pdo->prepare( 'SELECT * FROM ' . $table->name );
$stmt->execute();
Expand All @@ -94,6 +158,44 @@ protected function get_insert_statements( $table, $pdo ) {
}
}

/**
* Get the tables to exclude from the export.
*
* @return array|false|string[]
*/
protected function get_exclude_tables() {
$exclude_tables = isset( $this->args['exclude_tables'] ) ? explode( ',', $this->args['exclude_tables'] ) : [];
return array_merge(
$exclude_tables,
[
'_mysql_data_types_cache',
'sqlite_master',
'sqlite_sequence',
]
);
}

protected function display_result_message( $result_file ) {
if ( $this->is_stdout ) {
return;
}

if ( isset( $this->args['porcelain'] ) ) {
WP_CLI::line( $result_file );
} else {
WP_CLI::success( 'Export complete. File written to ' . $result_file );
}
}

/**
* Get the tables to include in the export.
*
* @return array|false|string[]
*/
protected function get_include_tables() {
return isset( $this->args['tables'] ) ? explode( ',', $this->args['tables'] ) : [];
}

/**
* Escape values for insert statement
*
Expand Down
5 changes: 4 additions & 1 deletion src/SQLite/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

class Import extends Base {


protected $unsupported_arguments = [
'skip-optimization',
'defaults',
Expand All @@ -17,12 +16,16 @@ class Import extends Base {
'dbpass',
];

protected $translator;
protected $args;

/**
* Execute the import command for SQLite.
*
* @throws Exception
*/
public function run( $sql_file_path, $args ) {
$this->args = $args;
$this->check_arguments( $args );
$this->load_dependencies();
$translator = new WP_SQLite_Translator();
Expand Down