PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 2.1.0
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v2.1.0
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / backup / cli.php

cli.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 2.1.0, at includes/backup/cli.php

158 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * StoreEngine full backup — WP-CLI commands.
4 *
5 * @version 1.0.0
6 */
7
8 namespace StoreEngine\Backup;
9
10 use WP_CLI;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * Export / import a complete StoreEngine backup.
18 */
19 class Cli {
20
21 /**
22 * Export all StoreEngine data into a single .zip archive.
23 *
24 * ## OPTIONS
25 *
26 * [--file=<path>]
27 * : Destination .zip path. Defaults to the private backups dir (path printed).
28 *
29 * [--groups=<list>]
30 * : Comma list of optional groups to include: licensing,logs,users,files.
31 * (Core store data + settings + catalog are always included.)
32 * Default: licensing.
33 *
34 * ## EXAMPLES
35 *
36 * wp storeengine backup export --file=/tmp/se.zip --groups=licensing,users
37 *
38 * @when after_wp_load
39 */
40 public function export( $args, $assoc_args ) {
41 $groups = array_filter( array_map( 'trim', explode( ',', (string) ( $assoc_args['groups'] ?? 'licensing' ) ) ) );
42 $opts = [
43 'licensing' => in_array( 'licensing', $groups, true ),
44 'logs' => in_array( 'logs', $groups, true ),
45 'users' => in_array( 'users', $groups, true ),
46 'files' => in_array( 'files', $groups, true ),
47 ];
48
49 $progress = WP_CLI\Utils\make_progress_bar( 'Exporting', 100 );
50 $last = 0;
51 $exporter = new Exporter( $opts, function ( $percent ) use ( $progress, &$last ) {
52 $tick = (int) $percent - $last;
53 if ( $tick > 0 ) {
54 $progress->tick( $tick );
55 $last = (int) $percent;
56 }
57 } );
58
59 $path = $exporter->run();
60 $progress->finish();
61
62 if ( ! empty( $assoc_args['file'] ) ) {
63 // phpcs:ignore WordPress.WP.AlternativeFunctions.rename_rename
64 rename( $path, $assoc_args['file'] );
65 $path = $assoc_args['file'];
66 }
67
68 WP_CLI::success( sprintf( 'Backup written to %s (%s)', $path, size_format( (int) filesize( $path ) ) ) );
69 }
70
71 /**
72 * Restore a StoreEngine backup (REPLACES existing StoreEngine data).
73 *
74 * ## OPTIONS
75 *
76 * --file=<path>
77 * : Path to the backup .zip.
78 *
79 * [--yes]
80 * : Skip the confirmation prompt.
81 *
82 * [--no-safety]
83 * : Skip the automatic pre-restore safety backup (not recommended).
84 *
85 * ## EXAMPLES
86 *
87 * wp storeengine backup import --file=/tmp/se.zip --yes
88 *
89 * @when after_wp_load
90 */
91 public function import( $args, $assoc_args ) {
92 $file = (string) ( $assoc_args['file'] ?? '' );
93 if ( ! is_file( $file ) ) {
94 WP_CLI::error( 'File not found: ' . $file );
95 }
96
97 $preview = ( new Importer() )->inspect( $file );
98 $manifest = $preview['manifest'];
99 WP_CLI::log( sprintf( 'Backup from %s (%s), generated %s.', $manifest['site_url'] ?? '?', $manifest['plugin_version'] ?? '?', $manifest['generated_at'] ?? '?' ) );
100 WP_CLI::log( sprintf( '%d tables; %d will be skipped (addon not installed).', count( (array) ( $manifest['tables'] ?? [] ) ), count( $preview['missing_tables'] ) ) );
101
102 WP_CLI::confirm( 'This will REPLACE all StoreEngine data on this site. Continue?', $assoc_args );
103
104 $progress = WP_CLI\Utils\make_progress_bar( 'Restoring', 100 );
105 $last = 0;
106 $importer = new Importer( function ( $percent ) use ( $progress, &$last ) {
107 $tick = (int) $percent - $last;
108 if ( $tick > 0 ) {
109 $progress->tick( $tick );
110 $last = (int) $percent;
111 }
112 } );
113
114 $result = $importer->run( $file, [ 'safety' => ! isset( $assoc_args['no-safety'] ) ] );
115 $progress->finish();
116
117 WP_CLI::log( sprintf( 'Restored %d tables, skipped %d.', count( $result['restored'] ), count( $result['skipped'] ) ) );
118 if ( ! empty( $result['safety_backup'] ) ) {
119 WP_CLI::log( 'Pre-restore safety backup: ' . $result['safety_backup'] );
120 }
121 WP_CLI::success( 'Restore complete.' );
122 }
123
124 /**
125 * Compare a backup's manifest row counts against the current database.
126 *
127 * ## OPTIONS
128 *
129 * --file=<path>
130 * : Path to the backup .zip.
131 *
132 * @when after_wp_load
133 */
134 public function verify( $args, $assoc_args ) {
135 global $wpdb;
136 $file = (string) ( $assoc_args['file'] ?? '' );
137 if ( ! is_file( $file ) ) {
138 WP_CLI::error( 'File not found: ' . $file );
139 }
140 $manifest = ( new Importer() )->inspect( $file )['manifest'];
141 $rows = [];
142 foreach ( (array) ( $manifest['tables'] ?? [] ) as $t ) {
143 $local = $wpdb->prefix . 'storeengine_' . $t['name'];
144 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
145 $live = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$local}`" );
146 $rows[] = [
147 'table' => $t['name'],
148 'in_backup' => (int) $t['row_count'],
149 'in_db' => $live,
150 'match' => ( (int) $t['row_count'] === $live ) ? 'yes' : 'NO',
151 ];
152 }
153 WP_CLI\Utils\format_items( 'table', $rows, [ 'table', 'in_backup', 'in_db', 'match' ] );
154 }
155 }
156
157 // End of file cli.php.
158