WP Staging – DB & File Duplicator & Migration - Version 2.0.3

Version Description

  • New: Complete rewrite of the code base
  • New: Batch processing allows to clone even huge sites without any timeouts
  • New: Preparation for WP QUADS PRO with ability to copy file changes back to live site
Download this release

Release Info

Developer ReneHermi
Plugin Icon 128x128 WP Staging – DB & File Duplicator & Migration
Version 2.0.3
Comparing to
See all releases

Code changes from version 2.0.4 to 2.0.3

CHANGELOG.md ADDED
File without changes
CONTRIBUTING.md ADDED
@@ -0,0 +1,38 @@
1
+ #Contribute To WP Staging
2
+
3
+ Community made patches, localisations, bug reports and contributions are always welcome.
4
+
5
+ When contributing please ensure you follow the guidelines below so that we can keep on top of things.
6
+
7
+ __Please Note:__ GitHub is for bug reports and contributions only.
8
+
9
+ ## Getting Started
10
+
11
+ * Submit a ticket for your issue, assuming one does not already exist.
12
+ * Raise it on our [Issue Tracker](https://github.com/rene-hermenau/wp-staging/issues)
13
+ * Clearly describe the issue including steps to reproduce the bug.
14
+ * Make sure you fill in the earliest version that you know has the issue as well as the version of WordPress you're using.
15
+
16
+ ## Making Changes
17
+
18
+ * Fork the repository on GitHub
19
+ * Make the changes to your forked repository
20
+ * Ensure you stick to the [WordPress Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards)
21
+ * When committing, reference your issue (if present) and include a note about the fix
22
+ * (coming soon) If possible, and if applicable, please also add/update unit tests for your changes
23
+ * Push the changes to your fork and submit a pull request to the 'master' branch of the WP Staging repository
24
+
25
+ ## Code Documentation
26
+
27
+ * We ensure that every WP Staging function is documented well and follows the standards set by phpDoc
28
+ * An example function can be found [here](https://gist.github.com/rene-hermenau/8d3d7ee0633ee2f64b4b)
29
+ * Please make sure that every function is documented so that when we update our API Documentation it will complete
30
+ * If you're adding/editing a function in a class, make sure to add `@access {private|public|protected}`
31
+ * Finally, please use tabs and not spaces. The tab indent size should be 4 for all WP Staging code.
32
+
33
+ At this point you're waiting on us to merge your pull request. We'll review all pull requests, and make suggestions and changes if necessary.
34
+
35
+ # Additional Resources
36
+ * [General GitHub Documentation](http://help.github.com/)
37
+ * [GitHub Pull Request documentation](http://help.github.com/send-pull-requests/)
38
+ * [PHPUnit Tests Guide](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html)
README.md ADDED
@@ -0,0 +1,32 @@
1
+ ### Welcome to the WP-Staging repository
2
+
3
+ ## Note ##
4
+
5
+ This is the latest developer version of WP-Staging for WordPress.
6
+
7
+ ## Installation ##
8
+
9
+ 1. You can clone the GitHub repository: `https://github.com/rene-hermenau/wp-staging.git`
10
+ 2. Or download it directly as a ZIP file: `https://github.com/rene-hermenau/wp-staging/archive/master.zip`
11
+ 3. Upload it via WordPress->Plugin->AddNew
12
+
13
+ This will download the latest developer copy of WP-Staging.
14
+
15
+ ## Bugs ##
16
+ If you find an issue, let us know [here](https://github.com/rene-hermenau/wp-staging/issues?state=open)!
17
+
18
+ ## Support ##
19
+ This is a developer's portal for WP-Staging
20
+
21
+ ## Contributions ##
22
+ Anyone is welcome to contribute to WP-Staging. Please read the [guidelines for contributing](https://github.com/rene-hermenau/wp-staging/blob/master/CONTRIBUTING.md) to this repository.
23
+
24
+ There are various ways you can contribute:
25
+
26
+ 1. Raise an [Issue](https://github.com/rene-hermenau/wp-staging/issues) on GitHub
27
+ 2. Send us a Pull Request with your bug fixes and/or new features
28
+ 3. Translate WP-Staging into different languages
29
+ 4. Provide feedback and suggestions on [enhancements](https://github.com/rene-hermenau/wp-staging/issues?direction=desc&labels=Enhancement&page=1&sort=created&state=open)
30
+
31
+ ## Contributors ##
32
+ [@rene-hermenau](https://github.com/rene-hermenau), [@ilgityildirim](https://github.com/ilgityildirim)
apps/Backend/Activation/Activation.php CHANGED
@@ -1,58 +1,47 @@
1
<?php
2
-
3
namespace WPStaging\Backend\Activation;
4
5
// No Direct Access
6
- if( !defined( "WPINC" ) ) {
7
- die;
8
}
9
10
use WPStaging\WPStaging;
11
- use WPStaging\Backend\Optimizer\Optimizer;
12
- use WPStaging\Cron\Cron;
13
14
class Activation {
15
-
16
- /**
17
- * Checks if another version of WPSTG (Pro) is active and deactivates it.
18
- * To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
19
- *
20
- * @param string $plugin
21
- *
22
- */
23
- public static function deactivate_other_instances( $plugin ) {
24
- if( !in_array( basename( $plugin ), array('wp-staging-pro.php', 'wp-staging.php') ) ) {
25
- return;
26
- }
27
- $plugin_to_deactivate = 'wp-staging.php';
28
- $deactivated_notice_id = '1';
29
- if( basename( $plugin ) == $plugin_to_deactivate ) {
30
- $plugin_to_deactivate = 'wp-staging-pro.php';
31
- $deactivated_notice_id = '2';
32
- }
33
- if( is_multisite() ) {
34
- $active_plugins = ( array ) get_site_option( 'active_sitewide_plugins', array() );
35
- $active_plugins = array_keys( $active_plugins );
36
- } else {
37
- $active_plugins = ( array ) get_option( 'active_plugins', array() );
38
- }
39
- foreach ( $active_plugins as $basename ) {
40
- if( false !== strpos( $basename, $plugin_to_deactivate ) ) {
41
- set_transient( 'wp_staging_deactivated_notice_id', $deactivated_notice_id, 1 * HOUR_IN_SECONDS );
42
- deactivate_plugins( $basename );
43
- return;
44
- }
45
- }
46
- }
47
-
48
- public static function install_dependancies() {
49
- // Register cron job.
50
- $cron = new \WPStaging\Cron\Cron;
51
- $cron->schedule_event();
52
-
53
- // Install Optimizer
54
- $optimizer = new Optimizer();
55
- $optimizer->installOptimizer();
56
- }
57
-
58
- }
1
<?php
2
namespace WPStaging\Backend\Activation;
3
4
// No Direct Access
5
+ if (!defined("WPINC"))
6
+ {
7
+ die;
8
}
9
10
use WPStaging\WPStaging;
11
12
class Activation {
13
+
14
+
15
+ /**
16
+ * Checks if another version of WPSTG (Pro) is active and deactivates it.
17
+ * To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
18
+ *
19
+ * @param string $plugin
20
+ *
21
+ */
22
+ public static function deactivate_other_instances( $plugin ) {
23
+ if ( ! in_array( basename( $plugin ), array( 'wp-staging-pro.php', 'wp-staging.php' ) ) ) {
24
+ return;
25
+ }
26
+
27
+ $plugin_to_deactivate = 'wp-staging.php';
28
+ $deactivated_notice_id = '1';
29
+ if ( basename( $plugin ) == $plugin_to_deactivate ) {
30
+ $plugin_to_deactivate = 'wp-staging-pro.php';
31
+ $deactivated_notice_id = '2';
32
+ }
33
+ if ( is_multisite() ) {
34
+ $active_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
35
+ $active_plugins = array_keys( $active_plugins );
36
+ } else {
37
+ $active_plugins = (array) get_option( 'active_plugins', array() );
38
+ }
39
+ foreach ( $active_plugins as $basename ) {
40
+ if ( false !== strpos( $basename, $plugin_to_deactivate ) ) {
41
+ set_transient( 'wp_staging_deactivated_notice_id', $deactivated_notice_id, 1 * HOUR_IN_SECONDS );
42
+ deactivate_plugins( $basename );
43
+ return;
44
+ }
45
+ }
46
+ }
47
+ }
apps/Backend/Administrator.php CHANGED
@@ -1,10 +1,10 @@
1
<?php
2
-
3
namespace WPStaging\Backend;
4
5
// No Direct Access
6
- if( !defined( "WPINC" ) ) {
7
- die;
8
}
9
10
use WPStaging\Backend\Modules\Jobs\Cancel;
@@ -23,616 +23,632 @@ use WPStaging\DI\InjectionAware;
23
use WPStaging\Backend\Modules\Views\Forms\Settings as FormSettings;
24
use WPStaging\Backend\Activation;
25
use WPStaging\WPStaging;
26
- use WPStaging\Backend\Pro\Modules\Jobs\Processing;
27
- use WPStaging\Backend\Pro\Licensing;
28
29
/**
30
* Class Administrator
31
* @package WPStaging\Backend
32
*/
33
- class Administrator extends InjectionAware {
34
-
35
- /**
36
- * @var string
37
- */
38
- private $path;
39
-
40
- /**
41
- * @var string
42
- */
43
- private $url;
44
-
45
- /**
46
- * Initialize class
47
- */
48
- public function initialize() {
49
- $this->defineHooks();
50
-
51
- // Path to backend
52
- $this->path = plugin_dir_path( __FILE__ );
53
-
54
- // URL to public backend folder
55
- $this->url = plugin_dir_url( __FILE__ ) . "public/";
56
-
57
- // Load plugins meta data
58
- $this->loadMeta();
59
- }
60
-
61
- /**
62
- * Load plugn meta data
63
- */
64
- public function loadMeta() {
65
- $run = new \WPStaging\Backend\Pluginmeta\Pluginmeta();
66
- }
67
-
68
- /**
69
- * Define Hooks
70
- */
71
- private function defineHooks() {
72
- // Get loader
73
- $loader = $this->di->get( "loader" );
74
-
75
- $Activation = new \WPStaging\Backend\Activation\Activation();
76
-
77
- $loader->addAction( "activated_plugin", $Activation, 'deactivate_other_instances' );
78
- $loader->addAction( "admin_menu", $this, "addMenu", 10 );
79
- $loader->addAction( "admin_init", $this, "setOptionFormElements" );
80
- $loader->addAction( "admin_init", $this, "upgrade" );
81
- $loader->addAction( "admin_post_wpstg_download_sysinfo", $this, "systemInfoDownload" );
82
- $loader->addAction( "admin_post_wpstg_export", $this, "export" );
83
- $loader->addAction( "admin_post_wpstg_import_settings", $this, "import" );
84
- $loader->addAction( "admin_notices", $this, "messages" );
85
-
86
- // Settings
87
- $settings = $this->di->get( "settings" );
88
-
89
- // Optimizer is ON
90
- if( $settings->isOptimizer() ) {
91
- $optimizer = new Optimizer( $this->di );
92
-
93
- $loader->addAction( "admin_init", $optimizer, "compatibility", 1 );
94
- $loader->addFilter( "option_active_plugins", $optimizer, "excludedPlugins" );
95
- $loader->addFilter( "site_option_active_sitewide_plugins", $optimizer, "excludedPlugins" );
96
- }
97
-
98
- // Ajax Requests
99
- $loader->addAction( "wp_ajax_wpstg_overview", $this, "ajaxOverview" );
100
- $loader->addAction( "wp_ajax_wpstg_scanning", $this, "ajaxScan" );
101
- $loader->addAction( "wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName" );
102
- $loader->addAction( "wp_ajax_wpstg_cloning", $this, "ajaxStartClone" );
103
- $loader->addAction( "wp_ajax_wpstg_clone_database", $this, "ajaxCloneDatabase" );
104
- $loader->addAction( "wp_ajax_wpstg_clone_prepare_directories", $this, "ajaxPrepareDirectories" );
105
- $loader->addAction( "wp_ajax_wpstg_clone_files", $this, "ajaxCopyFiles" );
106
- $loader->addAction( "wp_ajax_wpstg_clone_replace_data", $this, "ajaxReplaceData" );
107
- $loader->addAction( "wp_ajax_wpstg_clone_finish", $this, "ajaxFinish" );
108
- $loader->addAction( "wp_ajax_wpstg_confirm_delete_clone", $this, "ajaxDeleteConfirmation" );
109
- $loader->addAction( "wp_ajax_wpstg_delete_clone", $this, "ajaxDeleteClone" );
110
- $loader->addAction( "wp_ajax_wpstg_cancel_clone", $this, "ajaxCancelClone" );
111
- $loader->addAction( "wp_ajax_wpstg_hide_poll", $this, "ajaxHidePoll" );
112
- $loader->addAction( "wp_ajax_wpstg_hide_rating", $this, "ajaxHideRating" );
113
- $loader->addAction( "wp_ajax_wpstg_hide_beta", $this, "ajaxHideBeta" );
114
- $loader->addAction( "wp_ajax_wpstg_logs", $this, "ajaxLogs" );
115
- $loader->addAction( "wp_ajax_wpstg_check_disk_space", $this, "ajaxCheckFreeSpace" );
116
-
117
- // Ajax hooks pro Version
118
- $loader->addAction( "wp_ajax_wpstg_start_processing", $this, "ajaxProcessing" );
119
- $loader->addAction( "wp_ajax_wpstg_push_changes", $this, "ajaxPushChanges" );
120
- }
121
-
122
- /**
123
- * Register options form elements
124
- */
125
- public function setOptionFormElements() {
126
- register_setting( "wpstg_settings", "wpstg_settings", array($this, "sanitizeOptions") );
127
- }
128
-
129
- /**
130
- * Upgrade routine
131
- */
132
- public function upgrade() {
133
- $upgrade = new Upgrade\Upgrade();
134
- $upgrade->doUpgrade();
135
- }
136
-
137
- /**
138
- * Sanitize options data and delete the cache
139
- * @param array $data
140
- * @return array
141
- */
142
- public function sanitizeOptions( $data = array() ) {
143
- $sanitized = $this->sanitizeData( $data );
144
-
145
- add_settings_error( "wpstg-notices", '', __( "Settings updated.", "wpstg" ), "updated" );
146
-
147
- // Return sanitized data
148
- //return $sanitized;
149
- return apply_filters( "wpstg-settings", $sanitized, $data );
150
- }
151
-
152
- /**
153
- * @param array $data
154
- * @return array
155
- */
156
- private function sanitizeData( $data = array() ) {
157
- $sanitized = array();
158
-
159
- foreach ( $data as $key => $value ) {
160
- $sanitized[$key] = (is_array( $value )) ? $this->sanitizeData( $value ) : htmlspecialchars( $value );
161
- }
162
-
163
- return $sanitized;
164
- }
165
-
166
- /**
167
- * Add Admin Menu(s)
168
- */
169
- public function addMenu() {
170
-
171
- $logo = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGw9Im5vbmUiPgo8Zz48Zz48cGF0aCBzdHlsZT0iZmlsbDojZmZmIiAgZD0iTTEzNy42LDU2MS4zSDEzLjhIMTB2MzA2LjNsOTAuNy04My40QzE4OS42LDkwOC43LDMzNS4zLDk5MCw1MDAsOTkwYzI0OS45LDAsNDU2LjEtMTg3LjEsNDg2LjItNDI4LjhIODYyLjRDODMzLjMsNzM1LjEsNjgyLjEsODY3LjUsNTAwLDg2Ny41Yy0xMjksMC0yNDIuNS02Ni41LTMwOC4xLTE2Ny4ybDE1MS4zLTEzOS4xSDEzNy42eiIvPjxwYXRoIHN0eWxlPSJmaWxsOiNmZmYiICBkPSJNNTAwLDEwQzI1MC4xLDEwLDQzLjksMTk3LjEsMTMuOCw0MzguOGgxMjMuOEMxNjYuNywyNjQuOSwzMTcuOSwxMzIuNSw1MDAsMTMyLjVjMTMyLjksMCwyNDkuMyw3MC41LDMxMy44LDE3Ni4yTDY4My44LDQzOC44aDEyMi41aDU2LjJoMTIzLjhoMy44VjEzMi41bC04Ny43LDg3LjdDODEzLjgsOTMuMSw2NjYuNiwxMCw1MDAsMTB6Ii8+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvZz4KPC9zdmc+';
172
-
173
- // Main WP Staging Menu
174
- add_menu_page(
175
- "WP-Staging", __( "WP Staging", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage"), $logo
176
- );
177
-
178
- // Page: Clone
179
- add_submenu_page(
180
- "wpstg_clone", __( "WP Staging Jobs", "wpstg" ), __( "Start", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage")
181
- );
182
-
183
- // Page: Settings
184
- add_submenu_page(
185
- "wpstg_clone", __( "WP Staging Settings", "wpstg" ), __( "Settings", "wpstg" ), "manage_options", "wpstg-settings", array($this, "getSettingsPage")
186
- );
187
-
188
- // Page: Tools
189
- add_submenu_page(
190
- "wpstg_clone", __( "WP Staging Tools", "wpstg" ), __( "Tools", "wpstg" ), "manage_options", "wpstg-tools", array($this, "getToolsPage")
191
- );
192
-
193
- if( class_exists( 'WPStaging\Backend\Pro\Licensing\Licensing' ) ) {
194
- // Page: License
195
- add_submenu_page(
196
- "wpstg_clone", __( "WP Staging License", "wpstg" ), __( "License", "wpstg" ), "manage_options", "wpstg-license", array($this, "getLicensePage")
197
- );
198
- }
199
- }
200
-
201
- /**
202
- * Settings Page
203
- */
204
- public function getSettingsPage() {
205
- // Tabs
206
- $tabs = new Tabs( array(
207
- "general" => __( "General", "wpstg" )
208
- ) );
209
-
210
-
211
- $this->di
212
- // Set tabs
213
- ->set( "tabs", $tabs )
214
- // Forms
215
- ->set( "forms", new FormSettings( $tabs ) );
216
-
217
- require_once "{$this->path}views/settings/index.php";
218
- }
219
-
220
- /**
221
- * Clone Page
222
- */
223
- public function getClonePage() {
224
- // Existing clones
225
- $availableClones = get_option( "wpstg_existing_clones_beta", array() );
226
-
227
- require_once "{$this->path}views/clone/index.php";
228
- }
229
-
230
- /**
231
- * Tools Page
232
- */
233
- public function getToolsPage() {
234
- // Tabs
235
- $tabs = new Tabs( array(
236
- "import_export" => __( "Import/Export", "wpstg" ),
237
- "system_info" => __( "System Info", "wpstg" )
238
- ) );
239
-
240
- $this->di->set( "tabs", $tabs );
241
-
242
- $this->di->set( "systemInfo", new SystemInfo( $this->di ) );
243
-
244
- require_once "{$this->path}views/tools/index.php";
245
- }
246
-
247
- /**
248
- * System Information Download
249
- */
250
- public function systemInfoDownload() {
251
- if( !current_user_can( "update_plugins" ) ) {
252
- return;
253
- }
254
-
255
- nocache_headers();
256
- header( "Content-Type: text/plain" );
257
- header( "Content-Disposition: attachment; filename='wpstg-system-info.txt'" );
258
- echo wp_strip_all_tags( new SystemInfo( $this->di ) );
259
- }
260
-
261
- /**
262
- * Import JSON settings file
263
- */
264
- public function import() {
265
- if( empty( $_POST["wpstg_import_nonce"] ) ) {
266
- return;
267
- }
268
-
269
- if( !wp_verify_nonce( $_POST["wpstg_import_nonce"], "wpstg_import_nonce" ) ) {
270
- return;
271
- }
272
-
273
- if( !current_user_can( "update_plugins" ) ) {
274
- return;
275
- }
276
-
277
- $fileExtension = explode( '.', $_FILES["import_file"]["name"] );
278
- $fileExtension = end( $fileExtension );
279
- if( "json" !== $fileExtension ) {
280
- wp_die( "Please upload a valid .json file", "wpstg" );
281
- }
282
-
283
-
284
- $importFile = $_FILES["import_file"]["tmp_name"];
285
-
286
- if( empty( $importFile ) ) {
287
- wp_die( __( "Please upload a file to import", "wpstg" ) );
288
- }
289
-
290
- update_option( "wpstg_settings", json_decode( file_get_contents( $importFile, true ) ) );
291
-
292
- wp_safe_redirect( admin_url( "admin.php?page=wpstg-tools&amp;wpstg-message=settings-imported" ) );
293
-
294
- return;
295
- }
296
-
297
- /**
298
- * Export settings to JSON file
299
- */
300
- public function export() {
301
- if( empty( $_POST["wpstg_export_nonce"] ) ) {
302
- return;
303
- }
304
-
305
- if( !wp_verify_nonce( $_POST["wpstg_export_nonce"], "wpstg_export_nonce" ) ) {
306
- return;
307
- }
308
-
309
- if( !current_user_can( "manage_options" ) ) {
310
- return;
311
- }
312
-
313
- $settings = get_option( "wpstg_settings", array() );
314
-
315
- ignore_user_abort( true );
316
-
317
- if( !in_array( "set_time_limit", explode( ',', ini_get( "disable_functions" ) ) ) && !@ini_get( "safe_mode" ) ) {
318
- set_time_limit( 0 );
319
- }
320
-
321
- $fileName = apply_filters( "wpstg_settings_export_filename", "wpstg-settings-export-" . date( "m-d-Y" ) ) . ".json";
322
-
323
- nocache_headers();
324
- header( "Content-Type: application/json; charset=utf-8" );
325
- header( "Content-Disposition: attachment; filename={$fileName}" );
326
- header( "Expires: 0" );
327
-
328
- echo json_encode( $settings );
329
- }
330
-
331
- /**
332
- * Render a view file
333
- * @param string $file
334
- * @param array $vars
335
- * @return string
336
- */
337
- public function render( $file, $vars = array() ) {
338
- $fullPath = $this->path . "views" . DIRECTORY_SEPARATOR;
339
- $fullPath = str_replace( array('/', "\\"), DIRECTORY_SEPARATOR, $fullPath . $file . ".php" );
340
-
341
- if( !file_exists( $fullPath ) || !is_readable( $fullPath ) ) {
342
- return "Can't render : {$fullPath} either file doesn't exist or can't read it";
343
- }
344
-
345
- $contents = @file_get_contents( $fullPath );
346
-
347
- // Variables are set
348
- if( count( $vars ) > 0 ) {
349
- $vars = array_combine(
350
- array_map( function ($key) {
351
return "{{" . $key . "}}";
352
- }, array_keys( $vars )
353
- ), $vars
354
- );
355
-
356
- $contents = str_replace( array_keys( $vars ), array_values( $vars ), $contents );
357
- }
358
-
359
- return $contents;
360
- }
361
-
362
- /**
363
- * Ajax Overview
364
- */
365
- public function ajaxOverview() {
366
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
367
-
368
- // Existing clones
369
- $availableClones = get_option( "wpstg_existing_clones_beta", array() );
370
-
371
- // Get license data
372
- $license = get_option( 'wpstg_license_status' );
373
-
374
- if( \WPStaging\WPStaging::getSlug() === 'wp-staging-pro' ) {
375
- require_once "{$this->path}Pro/views/single-overview-pro.php";
376
- } else {
377
- require_once "{$this->path}views/clone/ajax/single-overview.php";
378
- }
379
-
380
- wp_die();
381
- }
382
-
383
- /**
384
- * Ajax Scan
385
- */
386
- public function ajaxScan() {
387
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
388
-
389
- // Scan
390
- $scan = new Scan();
391
- $scan->start();
392
-
393
- // Get Options
394
- $options = $scan->getOptions();
395
-
396
- require_once "{$this->path}views/clone/ajax/scan.php";
397
-
398
- wp_die();
399
- }
400
-
401
- /**
402
- * Ajax Check Clone Name
403
- */
404
- public function ajaxCheckCloneName() {
405
- $cloneName = sanitize_key( $_POST["cloneID"] );
406
- $cloneNameLength = strlen( $cloneName );
407
- $clones = get_option( "wpstg_existing_clones_beta", array() );
408
-
409
- // Check clone name length
410
- if( $cloneNameLength < 1 || $cloneNameLength > 16 ) {
411
- echo wp_send_json( array(
412
- "status" => "failed",
413
- "message" => "Clone name must be between 1 - 16 characters"
414
- ) );
415
- } elseif( array_key_exists( $cloneName, $clones ) ) {
416
- echo wp_send_json( array(
417
- "status" => "failed",
418
- "message" => "Clone name is already in use, please choose an another clone name"
419
- ) );
420
- }
421
-
422
- echo wp_send_json( array("status" => "success") );
423
- }
424
-
425
- /**
426
- * Ajax Start Clone (Basically just layout and saving data)
427
- */
428
- public function ajaxStartClone() {
429
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
430
-
431
- $cloning = new Cloning();
432
-
433
- if( !$cloning->save() ) {
434
- wp_die();
435
- }
436
-
437
- require_once "{$this->path}views/clone/ajax/start.php";
438
-
439
- wp_die();
440
- }
441
-
442
- /**
443
- * Ajax Clone Database
444
- */
445
- public function ajaxCloneDatabase() {
446
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
447
-
448
- $cloning = new Cloning();
449
-
450
- wp_send_json( $cloning->start() );
451
- }
452
-
453
- /**
454
- * Ajax Prepare Directories (get listing of files)
455
- */
456
- public function ajaxPrepareDirectories() {
457
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
458
-
459
- $cloning = new Cloning();
460
-
461
- wp_send_json( $cloning->start() );
462
- }
463
-
464
- /**
465
- * Ajax Clone Files
466
- */
467
- public function ajaxCopyFiles() {
468
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
469
-
470
- $cloning = new Cloning();
471
-
472
- wp_send_json( $cloning->start() );
473
- }
474
-
475
- /**
476
- * Ajax Replace Data
477
- */
478
- public function ajaxReplaceData() {
479
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
480
-
481
- $cloning = new Cloning();
482
-
483
- wp_send_json( $cloning->start() );
484
- }
485
-
486
- /**
487
- * Ajax Finish
488
- */
489
- public function ajaxFinish() {
490
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
491
-
492
- $cloning = new Cloning();
493
-
494
- wp_send_json( $cloning->start() );
495
- }
496
-
497
- /**
498
- * Ajax Delete Confirmation
499
- */
500
- public function ajaxDeleteConfirmation() {
501
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
502
-
503
- $delete = new Delete();
504
- $delete->setData();
505
-
506
- $clone = $delete->getClone();
507
-
508
- require_once "{$this->path}views/clone/ajax/delete-confirmation.php";
509
-
510
- wp_die();
511
- }
512
-
513
- /**
514
- * Delete clone
515
- */
516
- public function ajaxDeleteClone() {
517
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
518
-
519
- $delete = new Delete();
520
- wp_send_json( $delete->start() );
521
- }
522
-
523
- /**
524
- * Delete clone
525
- */
526
- public function ajaxCancelClone() {
527
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
528
-
529
- $cancel = new Cancel();
530
- wp_send_json( $cancel->start() );
531
- }
532
-
533
- /**
534
- * Admin Messages
535
- */
536
- public function messages() {
537
- $notice = new Notices( $this->path, $this->url );
538
-
539
- $run = $notice->messages();
540
- }
541
-
542
- /**
543
- * Ajax Hide Poll
544
- * @return mixed boolean | json
545
- */
546
- public function ajaxHidePoll() {
547
- if( false !== update_option( "wpstg_poll", "no" ) ) {
548
- wp_send_json( true );
549
- }
550
- return wp_send_json();
551
- }
552
-
553
- /**
554
- * Ajax Hide Rating
555
- * @return mixed bool | json
556
- */
557
- public function ajaxHideRating() {
558
- if( false !== update_option( "wpstg_rating", "no" ) ) {
559
- wp_send_json( true );
560
- }
561
- return wp_send_json();
562
- }
563
-
564
- /**
565
- * Ajax Hide Beta
566
- */
567
- public function ajaxHideBeta() {
568
- wp_send_json( update_option( "wpstg_beta", "no" ) );
569
- }
570
-
571
- /**
572
- * Clone logs
573
- */
574
- public function ajaxLogs() {
575
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
576
-
577
- $logs = new Logs();
578
- wp_send_json( $logs->start() );
579
- }
580
-
581
- /**
582
- * Ajax Checks Free Disk Space
583
- */
584
- public function ajaxCheckFreeSpace() {
585
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
586
-
587
- $scan = new Scan();
588
- return $scan->hasFreeDiskSpace();
589
- }
590
-
591
- /**
592
- * Ajax Start Push Changes Process
593
- */
594
- public function ajaxProcessing() {
595
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
596
-
597
- if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Scan' ) ) {
598
- return false;
599
- }
600
-
601
- // Scan
602
- $scan = new Pro\Modules\Jobs\Scan();
603
- $scan->start();
604
-
605
- // Get Options
606
- $options = $scan->getOptions();
607
-
608
- require_once "{$this->path}Pro/views/scan.php";
609
-
610
- wp_die();
611
- }
612
-
613
- /**
614
- * Ajax Start Pushing. Needs wp quads pro)
615
- */
616
- public function ajaxPushChanges() {
617
- check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
618
-
619
- if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Processing' ) ) {
620
- return false;
621
- }
622
- // Start the process
623
- $processing = new Processing();
624
- wp_send_json( $processing->start() );
625
- }
626
-
627
- /**
628
- * License Page
629
- */
630
- public function getLicensePage() {
631
-
632
- // Get license data
633
- $license = get_option( 'wpstg_license_status' );
634
-
635
- require_once "{$this->path}Pro/views/licensing.php";
636
- }
637
-
638
- }
1
<?php
2
namespace WPStaging\Backend;
3
4
// No Direct Access
5
+ if (!defined("WPINC"))
6
+ {
7
+ die;
8
}
9
10
use WPStaging\Backend\Modules\Jobs\Cancel;
23
use WPStaging\Backend\Modules\Views\Forms\Settings as FormSettings;
24
use WPStaging\Backend\Activation;
25
use WPStaging\WPStaging;
26
27
/**
28
* Class Administrator
29
* @package WPStaging\Backend
30
*/
31
+ class Administrator extends InjectionAware
32
+ {
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ private $path;
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ private $url;
43
+
44
+ /**
45
+ * Initialize class
46
+ */
47
+ public function initialize()
48
+ {
49
+ $this->defineHooks();
50
+
51
+ // Path to backend
52
+ $this->path = plugin_dir_path(__FILE__);
53
+
54
+ // URL to public backend folder
55
+ $this->url = plugin_dir_url(__FILE__) . "public/";
56
+
57
+ // Load plugins meta data
58
+ $this->loadMeta();
59
+
60
+ }
61
+
62
+ public function loadMeta(){
63
+ $run = new \WPStaging\Backend\Pluginmeta\Pluginmeta();
64
+ }
65
+
66
+ /**
67
+ * Define Hooks
68
+ */
69
+ private function defineHooks()
70
+ {
71
+ // Get loader
72
+ $loader = $this->di->get("loader");
73
+
74
+ $Activation = new \WPStaging\Backend\Activation\Activation();
75
+
76
+ $loader->addAction("activated_plugin", $Activation, 'deactivate_other_instances');
77
+ $loader->addAction("admin_menu", $this, "addMenu", 10);
78
+ $loader->addAction("admin_init", $this, "setOptionFormElements");
79
+ $loader->addAction("admin_init", $this, "upgrade");
80
+ $loader->addAction("admin_post_wpstg_download_sysinfo", $this, "systemInfoDownload");
81
+ $loader->addAction("admin_post_wpstg_export", $this, "export");
82
+ $loader->addAction("admin_post_wpstg_import_settings", $this, "import");
83
+ $loader->addAction("admin_notices", $this, "messages");
84
+
85
+ // Settings
86
+ $settings = $this->di->get("settings");
87
+
88
+ // Optimizer is ON
89
+ if ($settings->isOptimizer())
90
+ {
91
+ $optimizer = new Optimizer($this->di);
92
+
93
+ $loader->addAction("admin_init", $optimizer, "compatibility", 1);
94
+ $loader->addFilter("option_active_plugins", $optimizer, "excludedPlugins");
95
+ $loader->addFilter("site_option_active_sitewide_plugins", $optimizer, "excludedPlugins");
96
+ }
97
+
98
+ // Ajax Requests
99
+ $loader->addAction("wp_ajax_wpstg_overview", $this, "ajaxOverview");
100
+ $loader->addAction("wp_ajax_wpstg_scanning", $this, "ajaxScan");
101
+ $loader->addAction("wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName");
102
+ $loader->addAction("wp_ajax_wpstg_cloning", $this, "ajaxStartClone");
103
+ $loader->addAction("wp_ajax_wpstg_clone_database", $this, "ajaxCloneDatabase");
104
+ $loader->addAction("wp_ajax_wpstg_clone_prepare_directories", $this, "ajaxPrepareDirectories");
105
+ $loader->addAction("wp_ajax_wpstg_clone_files", $this, "ajaxCopyFiles");
106
+ $loader->addAction("wp_ajax_wpstg_clone_replace_data", $this, "ajaxReplaceData");
107
+ $loader->addAction("wp_ajax_wpstg_clone_finish", $this, "ajaxFinish");
108
+ $loader->addAction("wp_ajax_wpstg_confirm_delete_clone", $this, "ajaxDeleteConfirmation");
109
+ $loader->addAction("wp_ajax_wpstg_delete_clone", $this, "ajaxDeleteClone");
110
+ $loader->addAction("wp_ajax_wpstg_cancel_clone", $this, "ajaxCancelClone");
111
+ $loader->addAction("wp_ajax_wpstg_hide_poll", $this, "ajaxHidePoll");
112
+ $loader->addAction("wp_ajax_wpstg_hide_rating", $this, "ajaxHideRating");
113
+ $loader->addAction("wp_ajax_wpstg_hide_beta", $this, "ajaxHideBeta");
114
+ $loader->addAction("wp_ajax_wpstg_logs", $this, "ajaxLogs");
115
+ $loader->addAction("wp_ajax_wpstg_check_disk_space", $this, "ajaxCheckFreeSpace");
116
+ }
117
+
118
+ public function Activation(){
119
+ $run = new \WPStaging\Backend\Activation();
120
+ $run->deactivate_other_instances();
121
+ //echo 'activated';
122
+ }
123
+
124
+
125
+ /**
126
+ * Register options form elements
127
+ */
128
+ public function setOptionFormElements()
129
+ {
130
+ register_setting("wpstg_settings", "wpstg_settings", array($this, "sanitizeOptions"));
131
+ }
132
+
133
+ /**
134
+ * Upgrade routine
135
+ */
136
+ public function upgrade(){
137
+ $upgrade = new Upgrade\Upgrade();
138
+ $upgrade->doUpgrade();
139
+ }
140
+
141
+ /**
142
+ * Sanitize options data and delete the cache
143
+ * @param array $data
144
+ * @return array
145
+ */
146
+ public function sanitizeOptions($data = array())
147
+ {
148
+ $sanitized = $this->sanitizeData($data);
149
+
150
+ add_settings_error("wpstg-notices", '', __("Settings updated.", "wpstg"), "updated");
151
+
152
+ // Return sanitized data
153
+ //return $sanitized;
154
+ return apply_filters("wpstg-settings", $sanitized, $data);
155
+ }
156
+
157
+ /**
158
+ * @param array $data
159
+ * @return array
160
+ */
161
+ private function sanitizeData($data = array())
162
+ {
163
+ $sanitized = array();
164
+
165
+ foreach ($data as $key => $value)
166
+ {
167
+ $sanitized[$key] = (is_array($value)) ? $this->sanitizeData($value) : htmlspecialchars($value);
168
+ }
169
+
170
+ return $sanitized;
171
+ }
172
+
173
+ /**
174
+ * Add Admin Menu(s)
175
+ */
176
+ public function addMenu()
177
+ {
178
+
179
+ $logo = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGw9Im5vbmUiPgo8Zz48Zz48cGF0aCBzdHlsZT0iZmlsbDojZmZmIiAgZD0iTTEzNy42LDU2MS4zSDEzLjhIMTB2MzA2LjNsOTAuNy04My40QzE4OS42LDkwOC43LDMzNS4zLDk5MCw1MDAsOTkwYzI0OS45LDAsNDU2LjEtMTg3LjEsNDg2LjItNDI4LjhIODYyLjRDODMzLjMsNzM1LjEsNjgyLjEsODY3LjUsNTAwLDg2Ny41Yy0xMjksMC0yNDIuNS02Ni41LTMwOC4xLTE2Ny4ybDE1MS4zLTEzOS4xSDEzNy42eiIvPjxwYXRoIHN0eWxlPSJmaWxsOiNmZmYiICBkPSJNNTAwLDEwQzI1MC4xLDEwLDQzLjksMTk3LjEsMTMuOCw0MzguOGgxMjMuOEMxNjYuNywyNjQuOSwzMTcuOSwxMzIuNSw1MDAsMTMyLjVjMTMyLjksMCwyNDkuMyw3MC41LDMxMy44LDE3Ni4yTDY4My44LDQzOC44aDEyMi41aDU2LjJoMTIzLjhoMy44VjEzMi41bC04Ny43LDg3LjdDODEzLjgsOTMuMSw2NjYuNiwxMCw1MDAsMTB6Ii8+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvZz4KPC9zdmc+';
180
+
181
+ // Main WP Staging Menu
182
+ add_menu_page(
183
+ "WP-Staging",
184
+ __("WP Staging", "wpstg"),
185
+ "manage_options",
186
+ "wpstg_clone",
187
+ array($this, "getClonePage"),
188
+ $logo
189
+ );
190
+
191
+ // Page: Clone
192
+ add_submenu_page(
193
+ "wpstg_clone",
194
+ __("WP Staging Jobs", "wpstg"),
195
+ __("Start", "wpstg"),
196
+ "manage_options",
197
+ "wpstg_clone",
198
+ array($this, "getClonePage")
199
+ );
200
+
201
+ // Page: Settings
202
+ add_submenu_page(
203
+ "wpstg_clone",
204
+ __("WP Staging Settings", "wpstg"),
205
+ __("Settings", "wpstg"),
206
+ "manage_options",
207
+ "wpstg-settings",
208
+ array($this, "getSettingsPage")
209
+ );
210
+
211
+ // Page: Tools
212
+ add_submenu_page(
213
+ "wpstg_clone",
214
+ __("WP Staging Tools", "wpstg"),
215
+ __("Tools", "wpstg"),
216
+ "manage_options",
217
+ "wpstg-tools",
218
+ array($this, "getToolsPage")
219
+ );
220
+ }
221
+
222
+
223
+
224
+ /**
225
+ * Settings Page
226
+ */
227
+ public function getSettingsPage()
228
+ {
229
+ // Tabs
230
+ $tabs = new Tabs(array(
231
+ "general" => __("General", "wpstg")
232
+ ));
233
+
234
+
235
+ $this->di
236
+ // Set tabs
237
+ ->set("tabs", $tabs)
238
+ // Forms
239
+ ->set("forms", new FormSettings($tabs));
240
+
241
+ require_once "{$this->path}views/settings/index.php";
242
+ }
243
+
244
+ /**
245
+ * Clone Page
246
+ */
247
+ public function getClonePage()
248
+ {
249
+ // Existing clones
250
+ $availableClones = get_option("wpstg_existing_clones_beta", array());
251
+
252
+ require_once "{$this->path}views/clone/index.php";
253
+ }
254
+
255
+ /**
256
+ * Tools Page
257
+ */
258
+ public function getToolsPage()
259
+ {
260
+ // Tabs
261
+ $tabs = new Tabs(array(
262
+ "import_export" => __("Import/Export", "wpstg"),
263
+ "system_info" => __("System Info", "wpstg")
264
+ ));
265
+
266
+ $this->di->set("tabs", $tabs);
267
+
268
+ $this->di->set("systemInfo", new SystemInfo($this->di));
269
+
270
+ require_once "{$this->path}views/tools/index.php";
271
+ }
272
+
273
+ /**
274
+ * System Information Download
275
+ */
276
+ public function systemInfoDownload()
277
+ {
278
+ if (!current_user_can("update_plugins"))
279
+ {
280
+ return;
281
+ }
282
+
283
+ nocache_headers();
284
+ header("Content-Type: text/plain");
285
+ header("Content-Disposition: attachment; filename='wpstg-system-info.txt'");
286
+ echo wp_strip_all_tags(new SystemInfo($this->di));
287
+ }
288
+
289
+ /**
290
+ * Import JSON settings file
291
+ */
292
+ public function import()
293
+ {
294
+ if (empty($_POST["wpstg_import_nonce"]))
295
+ {
296
+ return;
297
+ }
298
+
299
+ if (!wp_verify_nonce($_POST["wpstg_import_nonce"], "wpstg_import_nonce"))
300
+ {
301
+ return;
302
+ }
303
+
304
+ if (!current_user_can("update_plugins"))
305
+ {
306
+ return;
307
+ }
308
+
309
+ $fileExtension = explode('.', $_FILES["import_file"]["name"]);
310
+ $fileExtension = end($fileExtension);
311
+ if ("json" !== $fileExtension)
312
+ {
313
+ wp_die("Please upload a valid .json file", "wpstg");
314
+ }
315
+
316
+
317
+ $importFile = $_FILES["import_file"]["tmp_name"];
318
+
319
+ if (empty($importFile))
320
+ {
321
+ wp_die(__("Please upload a file to import", "wpstg"));
322
+ }
323
+
324
+ update_option("wpstg_settings", json_decode(file_get_contents($importFile, true)));
325
+
326
+ wp_safe_redirect(admin_url("admin.php?page=wpstg-tools&amp;wpstg-message=settings-imported"));
327
+
328
+ return;
329
+ }
330
+
331
+ /**
332
+ * Export settings to JSON file
333
+ */
334
+ public function export()
335
+ {
336
+ if (empty($_POST["wpstg_export_nonce"]))
337
+ {
338
+ return;
339
+ }
340
+
341
+ if (!wp_verify_nonce($_POST["wpstg_export_nonce"], "wpstg_export_nonce"))
342
+ {
343
+ return;
344
+ }
345
+
346
+ if (!current_user_can("manage_options"))
347
+ {
348
+ return;
349
+ }
350
+
351
+ $settings = get_option("wpstg_settings", array());
352
+
353
+ ignore_user_abort(true);
354
+
355
+ if (!in_array("set_time_limit", explode(',', ini_get("disable_functions"))) && !@ini_get("safe_mode"))
356
+ {
357
+ set_time_limit(0);
358
+ }
359
+
360
+ $fileName = apply_filters("wpstg_settings_export_filename", "wpstg-settings-export-" . date("m-d-Y")) . ".json";
361
+
362
+ nocache_headers();
363
+ header("Content-Type: application/json; charset=utf-8");
364
+ header("Content-Disposition: attachment; filename={$fileName}");
365
+ header("Expires: 0");
366
+
367
+ echo json_encode($settings);
368
+ }
369
+
370
+
371
+ /**
372
+ * Render a view file
373
+ * @param string $file
374
+ * @param array $vars
375
+ * @return string
376
+ */
377
+ public function render($file, $vars = array())
378
+ {
379
+ $fullPath = $this->path . "views" . DIRECTORY_SEPARATOR;
380
+ $fullPath = str_replace(array('/', "\\"), DIRECTORY_SEPARATOR, $fullPath . $file . ".php");
381
+
382
+ if (!file_exists($fullPath) || !is_readable($fullPath))
383
+ {
384
+ return "Can't render : {$fullPath} either file doesn't exist or can't read it";
385
+ }
386
+
387
+ $contents = @file_get_contents($fullPath);
388
+
389
+ // Variables are set
390
+ if (count($vars) > 0)
391
+ {
392
+ $vars = array_combine(
393
+ array_map(function ($key)
394
+ {
395
return "{{" . $key . "}}";
396
+ },
397
+ array_keys($vars)
398
+ ),
399
+ $vars
400
+ );
401
+
402
+ $contents = str_replace(array_keys($vars), array_values($vars), $contents);
403
+ }
404
+
405
+ return $contents;
406
+ }
407
+
408
+ /**
409
+ * Ajax Overview
410
+ */
411
+ public function ajaxOverview()
412
+ {
413
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
414
+
415
+ // Existing clones
416
+ $availableClones = get_option("wpstg_existing_clones_beta", array());
417
+
418
+ require_once "{$this->path}views/clone/ajax/single-overview.php";
419
+
420
+ wp_die();
421
+ }
422
+
423
+ /**
424
+ * Ajax Scan
425
+ */
426
+ public function ajaxScan()
427
+ {
428
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
429
+
430
+ // Scan
431
+ $scan = new Scan();
432
+ $scan->start();
433
+
434
+ // Get Options
435
+ $options = $scan->getOptions();
436
+
437
+ require_once "{$this->path}views/clone/ajax/scan.php";
438
+
439
+ wp_die();
440
+ }
441
+
442
+ /**
443
+ * Ajax Check Clone Name
444
+ */
445
+ public function ajaxCheckCloneName()
446
+ {
447
+ $cloneName = sanitize_key($_POST["cloneID"]);
448
+ $cloneNameLength = strlen($cloneName);
449
+ $clones = get_option("wpstg_existing_clones_beta", array());
450
+
451
+ // Check clone name length
452
+ if ($cloneNameLength < 1 || $cloneNameLength > 16)
453
+ {
454
+ echo wp_send_json(array(
455
+ "status" => "failed",
456
+ "message" => "Clone name must be between 1 - 16 characters"
457
+ ));
458
+ }
459
+ elseif (array_key_exists($cloneName, $clones))
460
+ {
461
+ echo wp_send_json(array(
462
+ "status" => "failed",
463
+ "message" => "Clone name is already in use, please choose an another clone name"
464
+ ));
465
+ }
466
+
467
+ echo wp_send_json(array("status" => "success"));
468
+ }
469
+
470
+ /**
471
+ * Ajax Start Clone (Basically just layout and saving data)
472
+ */
473
+ public function ajaxStartClone()
474
+ {
475
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
476
+
477
+ $cloning = new Cloning();
478
+
479
+ if (!$cloning->save())
480
+ {
481
+ wp_die();
482
+ }
483
+
484
+ require_once "{$this->path}views/clone/ajax/start.php";
485
+
486
+ wp_die();
487
+ }
488
+
489
+ /**
490
+ * Ajax Clone Database
491
+ */
492
+ public function ajaxCloneDatabase()
493
+ {
494
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
495
+
496
+ $cloning = new Cloning();
497
+
498
+ wp_send_json($cloning->start());
499
+ }
500
+
501
+ /**
502
+ * Ajax Prepare Directories (get listing of files)
503
+ */
504
+ public function ajaxPrepareDirectories()
505
+ {
506
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
507
+
508
+ $cloning = new Cloning();
509
+
510
+ wp_send_json($cloning->start());
511
+ }
512
+
513
+ /**
514
+ * Ajax Clone Files
515
+ */
516
+ public function ajaxCopyFiles()
517
+ {
518
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
519
+
520
+ $cloning = new Cloning();
521
+
522
+ wp_send_json($cloning->start());
523
+ }
524
+
525
+ /**
526
+ * Ajax Replace Data
527
+ */
528
+ public function ajaxReplaceData()
529
+ {
530
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
531
+
532
+ $cloning = new Cloning();
533
+
534
+ wp_send_json($cloning->start());
535
+ }
536
+
537
+ /**
538
+ * Ajax Finish
539
+ */
540
+ public function ajaxFinish()
541
+ {
542
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
543
+
544
+ $cloning = new Cloning();
545
+
546
+ wp_send_json($cloning->start());
547
+ }
548
+
549
+ /**
550
+ * Ajax Delete Confirmation
551
+ */
552
+ public function ajaxDeleteConfirmation()
553
+ {
554
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
555
+
556
+ $delete = new Delete();
557
+ $delete->setData();
558
+
559
+ $clone = $delete->getClone();
560
+
561
+ require_once "{$this->path}views/clone/ajax/delete-confirmation.php";
562
+
563
+ wp_die();
564
+ }
565
+
566
+ /**
567
+ * Delete clone
568
+ */
569
+ public function ajaxDeleteClone()
570
+ {
571
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
572
+
573
+ $delete = new Delete();
574
+ wp_send_json($delete->start());
575
+ }
576
+
577
+ /**
578
+ * Delete clone
579
+ */
580
+ public function ajaxCancelClone()
581
+ {
582
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
583
+
584
+ $cancel = new Cancel();
585
+ wp_send_json($cancel->start());
586
+ }
587
+
588
+ /**
589
+ * Admin Messages
590
+ */
591
+ public function messages()
592
+ {
593
+ $notice = new Notices($this->path, $this->url);
594
+
595
+ $run = $notice->messages();
596
+ }
597
+
598
+ /**
599
+ * Ajax Hide Poll
600
+ * @return mixed boolean | json
601
+ */
602
+ public function ajaxHidePoll()
603
+ {
604
+ if( false !== update_option( "wpstg_poll", "no" ) ) {
605
+ wp_send_json( true );
606
+ }
607
+ return wp_send_json();
608
+ }
609
+
610
+ /**
611
+ * Ajax Hide Rating
612
+ * @return mixed bool | json
613
+ */
614
+ public function ajaxHideRating()
615
+ {
616
+ if( false !== update_option( "wpstg_rating", "no" ) ) {
617
+ wp_send_json( true );
618
+ }
619
+ return wp_send_json();
620
+ }
621
+
622
+ /**
623
+ * Ajax Hide Beta
624
+ */
625
+ public function ajaxHideBeta()
626
+ {
627
+ wp_send_json(update_option("wpstg_beta", "no"));
628
+ }
629
+
630
+ /**
631
+ * Clone logs
632
+ */
633
+ public function ajaxLogs()
634
+ {
635
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
636
+
637
+ $logs = new Logs();
638
+ wp_send_json($logs->start());
639
+ }
640
+
641
+ /**
642
+ * Ajax Checks Free Disk Space
643
+ */
644
+ public function ajaxCheckFreeSpace()
645
+ {
646
+ check_ajax_referer("wpstg_ajax_nonce", "nonce");
647
+
648
+ $scan = new Scan();
649
+ return $scan->hasFreeDiskSpace();
650
+ }
651
+
652
+
653
+
654
+ }
apps/Backend/Modules/Jobs/Delete.php CHANGED
@@ -2,7 +2,7 @@
2
namespace WPStaging\Backend\Modules\Jobs;
3
4
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
5
- //use WPStaging\Utils\Directories;
6
use WPStaging\Utils\Logger;
7
use WPStaging\WPStaging;
8
@@ -75,11 +75,19 @@ class Delete extends Job
75
if (empty($clones) || !isset($clones[$name]))
76
{
77
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
78
- //throw new CloneNotFoundException();
79
}
80
81
$this->clone = $clones[$name];
82
$this->clone["name"] = $name;
83
84
$this->clone = (object) $this->clone;
85
@@ -93,6 +101,10 @@ class Delete extends Job
93
{
94
$wpdb = WPStaging::getInstance()->get("wpdb");
95
96
$tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
97
98
$this->tables = array();
@@ -107,8 +119,8 @@ class Delete extends Job
107
108
$this->tables = json_decode(json_encode($this->tables));
109
}
110
-
111
- /**
112
* Format bytes into human readable form
113
* @param int $bytes
114
* @param int $precision
@@ -130,7 +142,6 @@ class Delete extends Job
130
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
131
}
132
133
-
134
/**
135
* @return false
136
*/
@@ -167,27 +178,25 @@ class Delete extends Job
167
/**
168
* Get job data
169
*/
170
- private function getJob() {
171
- $this->job = $this->cache->get( "delete_job_{$this->clone->name}" );
172
-
173
-
174
- if( null !== $this->job ) {
175
- return;
176
- }
177
178
- // Generate JOB
179
- $this->job = ( object ) array(
180
- "current" => "tables",
181
- "nextDirectoryToDelete" => $this->clone->path,
182
- "name" => $this->clone->name
183
- );
184
185
- $this->cache->save( "delete_job_{$this->clone->name}", $this->job );
186
- }
187
-
188
189
190
- /**
191
* @return bool
192
*/
193
private function updateJob()
@@ -260,43 +269,8 @@ class Delete extends Job
260
$length = strlen($needle);
261
return (substr($haystack, 0, $length) === $needle);
262
}
263
-
264
- /**
265
- * Delete a specific directory and all of its subfolders in a native way without using any external caching data
266
- *
267
- * @param array $dir
268
- * @param array $excluded_dirs
269
- * @return boolean false when its finished
270
- */
271
- // function deleteDirectoryNative( $dir = '' ) {
272
- //
273
- // if( !file_exists( $dir ) ) {
274
- // return $this->isFinished();
275
- // }
276
- //
277
- // if( !is_dir( $dir ) || is_link( $dir ) ) {
278
- // unlink( $dir );
279
- // return $this->isFinished();
280
- // }
281
- // foreach ( scandir( $dir ) as $item ) {
282
- // if( $item == '.' || $item == '..' ) {
283
- // continue;
284
- // }
285
- // if( !$this->deleteDirectoryNative( $dir . "/" . $item, false ) ) {
286
- // //chmod( $dir . "/" . $item, 0777 );
287
- // //if( !$this->deleteDirectoryNative( $dir . "/" . $item, false ) ){
288
- // //return false;
289
- // //}
290
- // }
291
- // };
292
- //
293
- // rmdir( $dir );
294
- // return $this->isFinished();
295
- // }
296
-
297
298
-
299
- /**
300
* Delete Directories
301
*/
302
public function deleteDirectory()
@@ -418,8 +392,6 @@ class Delete extends Job
418
$this->cache->delete("delete_job_{$this->clone->name}");
419
$this->cache->delete("delete_directories_{$this->clone->name}");
420
421
- //return true;
422
- $response = array('delete' => 'finished');
423
- wp_die(json_encode($response));
424
}
425
}
2
namespace WPStaging\Backend\Modules\Jobs;
3
4
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
5
+ use WPStaging\Utils\Directories;
6
use WPStaging\Utils\Logger;
7
use WPStaging\WPStaging;
8
75
if (empty($clones) || !isset($clones[$name]))
76
{
77
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
78
+ throw new CloneNotFoundException();
79
}
80
81
$this->clone = $clones[$name];
82
$this->clone["name"] = $name;
83
+ // $this->clone["size"] = null;
84
+ //
85
+ // if (isset($this->settings->checkDirectorySize) || '1' === $this->settings->checkDirectorySize)
86
+ // {
87
+ // $directories = new Directories();
88
+ // $this->clone["size"] = $this->formatSize($directories->size($this->clone));
89
+ // unset($directories);
90
+ // }
91
92
$this->clone = (object) $this->clone;
93
101
{
102
$wpdb = WPStaging::getInstance()->get("wpdb");
103
104
+ // if ($this->clone['version']){
105
+ //
106
+ // }
107
+
108
$tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
109
110
$this->tables = array();
119
120
$this->tables = json_decode(json_encode($this->tables));
121
}
122
+
123
+ /**
124
* Format bytes into human readable form
125
* @param int $bytes
126
* @param int $precision
142
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
143
}
144
145
/**
146
* @return false
147
*/
178
/**
179
* Get job data
180
*/
181
+ private function getJob()
182
+ {
183
+ $this->job = $this->cache->get("delete_job_{$this->clone->name}");
184
185
+ if (null !== $this->job)
186
+ {
187
+ return;
188
+ }
189
190
+ // Generate JOB
191
+ $this->job = (object) array(
192
+ "current" => "tables",
193
+ "nextDirectoryToDelete" => $this->clone->path
194
+ );
195
196
+ $this->cache->save("delete_job_{$this->clone->name}", $this->job);
197
+ }
198
199
+ /**
200
* @return bool
201
*/
202
private function updateJob()
269
$length = strlen($needle);
270
return (substr($haystack, 0, $length) === $needle);
271
}
272
273
+ /**
274
* Delete Directories
275
*/
276
public function deleteDirectory()
392
$this->cache->delete("delete_job_{$this->clone->name}");
393
$this->cache->delete("delete_directories_{$this->clone->name}");
394
395
+ return true;
396
}
397
}
apps/Backend/Modules/Jobs/Delete_deprecated.php DELETED
@@ -1,397 +0,0 @@
1
- <?php
2
- namespace WPStaging\Backend\Modules\Jobs;
3
-
4
- use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
5
- //use WPStaging\Utils\Directories;
6
- use WPStaging\Utils\Logger;
7
- use WPStaging\WPStaging;
8
-
9
- /**
10
- * Class Delete
11
- * @package WPStaging\Backend\Modules\Jobs
12
- */
13
- class Delete_deprecated extends Job
14
- {
15
-
16
- /**
17
- * @var false
18
- */
19
- private $clone = false;
20
-
21
- /**
22
- * @var null|object
23
- */
24
- private $tables = null;
25
-
26
- /**
27
- * @var object|null
28
- */
29
- private $job = null;
30
-
31
- /**
32
- * @var bool
33
- */
34
- private $forceDeleteDirectories = false;
35
-
36
- /**
37
- * Sets Clone and Table Records
38
- * @param null|array $clone
39
- */
40
- public function setData($clone = null)
41
- {
42
- if (!is_array($clone))
43
- {
44
- $this->getCloneRecords();
45
- }
46
- else
47
- {
48
- $this->clone = (object) $clone;
49
- $this->forceDeleteDirectories = true;
50
- }
51
-
52
- $this->getTableRecords();
53
- }
54
-
55
- /**
56
- * Get clone
57
- * @param null|string $name
58
- * @throws CloneNotFoundException
59
- */
60
- private function getCloneRecords($name = null)
61
- {
62
- if (null === $name && !isset($_POST["clone"]))
63
- {
64
- $this->log("Clone name is not set", Logger::TYPE_FATAL);
65
- throw new CloneNotFoundException();
66
- }
67
-
68
- if (null === $name)
69
- {
70
- $name = $_POST["clone"];
71
- }
72
-
73
- $clones = get_option("wpstg_existing_clones_beta", array());
74
-
75
- if (empty($clones) || !isset($clones[$name]))
76
- {
77
- $this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
78
- throw new CloneNotFoundException();
79
- }
80
-
81
- $this->clone = $clones[$name];
82
- $this->clone["name"] = $name;
83
- // $this->clone["size"] = null;
84
- //
85
- // if (isset($this->settings->checkDirectorySize) || '1' === $this->settings->checkDirectorySize)
86
- // {
87
- // $directories = new Directories();
88
- // $this->clone["size"] = $this->formatSize($directories->size($this->clone));
89
- // unset($directories);
90
- // }
91
-
92
- $this->clone = (object) $this->clone;
93
-
94
- unset($clones);
95
- }
96
-
97
- /**
98
- * Get Tables
99
- */
100
- private function getTableRecords()
101
- {
102
- $wpdb = WPStaging::getInstance()->get("wpdb");
103
-
104
- // if ($this->clone['version']){
105
- //
106
- // }
107
-
108
- $tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
109
-
110
- $this->tables = array();
111
-
112
- foreach ($tables as $table)
113
- {
114
- $this->tables[] = array(
115
- "name" => $table->Name,
116
- "size" => $this->formatSize(($table->Data_length + $table->Index_length))
117
- );
118
- }
119
-
120
- $this->tables = json_decode(json_encode($this->tables));
121
- }
122
-
123
- /**
124
- * Format bytes into human readable form
125
- * @param int $bytes
126
- * @param int $precision
127
- * @return string
128
- */
129
- public function formatSize($bytes, $precision = 2)
130
- {
131
- if ((int) $bytes < 1)
132
- {
133
- return '';
134
- }
135
-
136
- $units = array('B', "KB", "MB", "GB", "TB");
137
-
138
- $bytes = (int) $bytes;
139
- $base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
140
- $pow = pow(1000, $base - floor($base)); // Same rule for 1000
141
-
142
- return round($pow, $precision) . ' ' . $units[(int) floor($base)];
143
- }
144
-
145
- /**
146
- * @return false
147
- */
148
- public function getClone()
149
- {
150
- return $this->clone;
151
- }
152
-
153
- /**
154
- * @return null|object
155
- */
156
- public function getTables()
157
- {
158
- return $this->tables;
159
- }
160
-
161
- /**
162
- * Start Module
163
- * @param null|array $clone
164
- * @return bool
165
- */
166
- public function start($clone = null)
167
- {
168
- // Set data
169
- $this->setData($clone);
170
-
171
- // Get the job first
172
- $this->getJob();
173
-
174
- $method = "delete" . ucwords($this->job->current);
175
- return $this->{$method}();
176
- }
177
-
178
- /**
179
- * Get job data
180
- */
181
- private function getJob()
182
- {
183
- $this->job = $this->cache->get("delete_job_{$this->clone->name}");
184
-
185
- if (null !== $this->job)
186
- {
187
- return;
188
- }
189
-
190
- // Generate JOB
191
- $this->job = (object) array(
192
- "current" => "tables",
193
- "nextDirectoryToDelete" => $this->clone->path
194
- );
195
-
196
- $this->cache->save("delete_job_{$this->clone->name}", $this->job);
197
- }
198
-
199
- /**
200
- * @return bool
201
- */
202
- private function updateJob()
203
- {
204
- $this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
205
- return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
206
- }
207
-
208
- /**
209
- * @return array
210
- */
211
- private function getTablesToRemove()
212
- {
213
- $tables = $this->getTableNames();
214
-
215
- if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"]))
216
- {
217
- return $tables;
218
- }
219
-
220
- return array_diff($tables, $_POST["excludedTables"]);
221
- }
222
-
223
- /**
224
- * @return array
225
- */
226
- private function getTableNames()
227
- {
228
- return (!is_array($this->tables)) ? array() : array_map(function($value) {
229
- return ($value->name);
230
- }, $this->tables);
231
- }
232
-
233
- /**
234
- * Delete Tables
235
- */
236
- public function deleteTables()
237
- {
238
- if ($this->isOverThreshold())
239
- {
240
- return;
241
- }
242
-
243
- $wpdb = WPStaging::getInstance()->get("wpdb");
244
-
245
- foreach ($this->getTablesToRemove() as $table)
246
- {
247
- // PROTECTION: Never delete any table that beginns with wp prefix of live site
248
- if($this->startsWith($table, $wpdb->prefix)){
249
- $this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
250
- return false;
251
- } else{
252
- $wpdb->query("DROP TABLE {$table}");
253
- }
254
- }
255
-
256
- // Move on to the next
257
- $this->job->current = "directory";
258
- $this->updateJob();
259
- }
260
-
261
- /**
262
- * Check if a strings start with a specific string
263
- * @param string $haystack
264
- * @param string $needle
265
- * @return bool
266
- */
267
- protected function startsWith($haystack, $needle)
268
- {
269
- $length = strlen($needle);
270
- return (substr($haystack, 0, $length) === $needle);
271
- }
272
-
273
- /**
274
- * Delete Directories
275
- */
276
- public function deleteDirectory()
277
- {
278
- // No deleting directories or root of this clone is deleted
279
- if ($this->isDirectoryDeletingFinished())
280
- {
281
- $this->job->current = "finish";
282
- $this->updateJob();
283
- return;
284
- }
285
-
286
- $this->processDirectory($this->job->nextDirectoryToDelete);
287
-
288
- return;
289
- }
290
-
291
- /**
292
- * @return bool
293
- */
294
- public function isDirectoryDeletingFinished()
295
- {
296
- return (
297
- (false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
298
- !is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
299
- );
300
- }
301
-
302
- /**
303
- * Delete contents of the directory if there are no directories in it and then delete itself
304
- * @param string $path
305
- * @return mixed
306
- */
307
- private function processDirectory($path)
308
- {
309
- // We hit the limit, stop
310
- if ($this->shouldStop($path))
311
- {
312
- $this->updateJob();
313
- return false;
314
- }
315
-
316
- $this->totalRecursion++;
317
-
318
- $contents = new \DirectoryIterator($path);
319
-
320
- foreach ($contents as $content)
321
- {
322
- // Skip dots
323
- if ($content->isDot())
324
- {
325
- continue;
326
- }
327
-
328
- // Get into the directory
329
- if (!$content->isLink() && $content->isDir())
330
- {
331
- return $this->processDirectory($content->getRealPath());
332
- }
333
-
334
- // Delete file
335
- if ($content->isFile())
336
- {
337
- @unlink($content->getRealPath());
338
- }
339
- }
340
-
341
- // Delete directory
342
- $this->job->lastDeletedDirectory = realpath($path . "/..");
343
- @rmdir($path);
344
- $this->updateJob();
345
- $this->processDirectory($this->job->nextDirectoryToDelete);
346
- }
347
-
348
- /**
349
- * @param string $path
350
- * @return bool
351
- */
352
- private function shouldStop($path)
353
- {
354
- // Just to make sure the root dir is never deleted!
355
- if ($path === get_home_path()){
356
- $this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
357
- return true;
358
- }
359
-
360
- // Check if threshold is reached and is valid dir
361
- return (
362
- $this->isOverThreshold() ||
363
- !is_dir($path) ||
364
- $this->isDirectoryDeletingFinished()
365
- );
366
- }
367
-
368
- /**
369
- * Finish / Update Existing Clones
370
- */
371
- public function deleteFinish()
372
- {
373
- $existingClones = get_option("wpstg_existing_clones_beta", array());
374
-
375
- // Check if clones still exist
376
- $this->log("Verifying existing clones...");
377
- foreach ($existingClones as $name => $clone)
378
- {
379
- if (!is_dir($clone["path"]))
380
- {
381
- unset($existingClones[$name]);
382
- }
383
- }
384
- $this->log("Existing clones verified!");
385
-
386
- if (false === update_option("wpstg_existing_clones_beta", $existingClones))
387
- {
388
- $this->log("Failed to save {$this->options->clone}'s clone job data to database'");
389
- }
390
-
391
- // Delete cached file
392
- $this->cache->delete("delete_job_{$this->clone->name}");
393
- $this->cache->delete("delete_directories_{$this->clone->name}");
394
-
395
- return true;
396
- }
397
- }
apps/Backend/Modules/Jobs/Delete_new.php DELETED
@@ -1,382 +0,0 @@
1
- <?php
2
- namespace WPStaging\Backend\Modules\Jobs;
3
-
4
- use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
5
- //use WPStaging\Utils\Directories;
6
- use WPStaging\Utils\Logger;
7
- use WPStaging\WPStaging;
8
-
9
- /**
10
- * Class Delete
11
- * @package WPStaging\Backend\Modules\Jobs
12
- */
13
- class Delete_new extends Job
14
- {
15
-
16
- /**
17
- * @var false
18
- */
19
- private $clone = false;
20
-
21
- /**
22
- * @var null|object
23
- */
24
- private $tables = null;
25
-
26
- /**
27
- * @var object|null
28
- */
29
- private $job = null;
30
-
31
- /**
32
- * @var bool
33
- */
34
- private $forceDeleteDirectories = false;
35
-
36
- /**
37
- * Sets Clone and Table Records
38
- * @param null|array $clone
39
- */
40
- public function setData($clone = null)
41
- {
42
- if (!is_array($clone))
43
- {
44
- $this->getCloneRecords();
45
- }
46
- else
47
- {
48
- $this->clone = (object) $clone;
49
- $this->forceDeleteDirectories = true;
50
- }
51
-
52
- $this->getTableRecords();
53
- }
54
-
55
- /**
56
- * Get clone
57
- * @param null|string $name
58
- * @throws CloneNotFoundException
59
- */
60
- private function getCloneRecords($name = null)
61
- {
62
- if (null === $name && !isset($_POST["clone"]))
63
- {
64
- $this->log("Clone name is not set", Logger::TYPE_FATAL);
65
- throw new CloneNotFoundException();
66
- }
67
-
68
- if (null === $name)
69
- {
70
- $name = $_POST["clone"];
71
- }
72
-
73
- $clones = get_option("wpstg_existing_clones_beta", array());
74
-
75
- if (empty($clones) || !isset($clones[$name]))
76
- {
77
- $this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
78
- throw new CloneNotFoundException();
79
- }
80
-
81
- $this->clone = $clones[$name];
82
- $this->clone["name"] = $name;
83
- $this->clone = (object) $this->clone;
84
-
85
- unset($clones);
86
- }
87
-
88
- /**
89
- * Get Tables
90
- */
91
- private function getTableRecords()
92
- {
93
- $wpdb = WPStaging::getInstance()->get("wpdb");
94
-
95
- $tables = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wpstg{$this->clone->number}_%'");
96
-
97
- $this->tables = array();
98
-
99
- foreach ($tables as $table)
100
- {
101
- $this->tables[] = array(
102
- "name" => $table->Name,
103
- "size" => $this->formatSize(($table->Data_length + $table->Index_length))
104
- );
105
- }
106
-
107
- $this->tables = json_decode(json_encode($this->tables));
108
- }
109
-
110
- /**
111
- * @return false
112
- */
113
- public function getClone()
114
- {
115
- return $this->clone;
116
- }
117
-
118
- /**
119
- * @return null|object
120
- */
121
- public function getTables()
122
- {
123
- return $this->tables;
124
- }
125
-
126
- /**
127
- * Start Module
128
- * @param null|array $clone
129
- * @return bool
130
- */
131
- public function start($clone = null)
132
- {
133
- // Set data
134
- $this->setData($clone);
135
-
136
- // Get the job first
137
- $this->getJob();
138
-
139
- $method = "delete" . ucwords($this->job->current);
140
- return $this->{$method}();
141
- }
142
-
143
-
144
-
145
- /**
146
- * Get job data
147
- */
148
- private function getJob()
149
- {
150
- $this->job = $this->cache->get("delete_job_{$this->clone->name}");
151
-
152
- if (null !== $this->job)
153
- {
154
- return;
155
- }
156
-
157
- // Generate JOB
158
- $this->job = (object) array(
159
- "current" => "tables",
160
- "nextDirectoryToDelete" => $this->clone->path
161
- );
162
-
163
- $this->cache->save("delete_job_{$this->clone->name}", $this->job);
164
- }
165
-
166
- /**
167
- * Delete Directories
168
- */
169
- // public function deleteDirectory()
170
- // {
171
- // // No deleting directories or root of this clone is deleted
172
- // if ($this->isDirectoryDeletingFinished())
173
- // {
174
- // $this->job->current = "finish";
175
- // $this->updateJob();
176
- // return;
177
- // }
178
- //
179
- // $this->processDirectory($this->job->nextDirectoryToDelete);
180
- //
181
- // return;
182
- // }
183
-
184
- public function deleteDirectory(){
185
- // Just to make sure the root dir is never deleted!
186
- if ($this->clone->path === get_home_path()){
187
- $this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
188
- return false;
189
- }
190
-
191
- $files = glob($this->clone->path . '/*');
192
- foreach ($files as $file) {
193
- is_dir($file) ? $this->deleteDirectory($file) : unlink($file);
194
- }
195
- rmdir($path);
196
- $this->processDirectory($this->job->nextDirectoryToDelete);
197
- return;
198
- }
199
-
200
- /**
201
- * @return bool
202
- */
203
- private function updateJob()
204
- {
205
- $this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
206
- return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
207
- }
208
-
209
- /**
210
- * @return array
211
- */
212
- private function getTablesToRemove()
213
- {
214
- $tables = $this->getTableNames();
215
-
216
- if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"]))
217
- {
218
- return $tables;
219
- }
220
-
221
- return array_diff($tables, $_POST["excludedTables"]);
222
- }
223
-
224
- /**
225
- * @return array
226
- */
227
- private function getTableNames()
228
- {
229
- return (!is_array($this->tables)) ? array() : array_map(function($value) {
230
- return ($value->name);
231
- }, $this->tables);
232
- }
233
-
234
- /**
235
- * Delete Tables
236
- */
237
- public function deleteTables()
238
- {
239
- if ($this->isOverThreshold())
240
- {
241
- return;
242
- }
243
-
244
- $wpdb = WPStaging::getInstance()->get("wpdb");
245
-
246
- foreach ($this->getTablesToRemove() as $table)
247
- {
248
- // PROTECTION: Never delete any table that beginns with wp prefix of live site
249
- if($this->startsWith($table, $wpdb->prefix)){
250
- $this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
251
- return false;
252
- } else{
253
- $wpdb->query("DROP TABLE {$table}");
254
- }
255
- }
256
-
257
- // Move on to the next
258
- $this->job->current = "directory";
259
- $this->updateJob();
260
- }
261
-
262
- /**
263
- * Check if a strings start with a specific string
264
- * @param string $haystack
265
- * @param string $needle
266
- * @return bool
267
- */
268
- protected function startsWith($haystack, $needle)
269
- {
270
- $length = strlen($needle);
271
- return (substr($haystack, 0, $length) === $needle);
272
- }
273
-
274
-
275
-
276
- /**
277
- * @return bool
278
- */
279
- public function isDirectoryDeletingFinished()
280
- {
281
- return (
282
- (false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
283
- !is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
284
- );
285
- }
286
-
287
- /**
288
- * Delete contents of the directory if there are no directories in it and then delete itself
289
- * @param string $path
290
- * @return mixed
291
- */
292
- private function processDirectory($path)
293
- {
294
- // We hit the limit, stop
295
- if ($this->shouldStop($path))
296
- {
297
- $this->updateJob();
298
- return false;
299
- }
300
-
301
- $this->totalRecursion++;
302
-
303
- $contents = new \DirectoryIterator($path);
304
-
305
- foreach ($contents as $content)
306
- {
307
- // Skip dots
308
- if ($content->isDot())
309
- {
310
- continue;
311
- }
312
-
313
- // Get into the directory
314
- if (!$content->isLink() && $content->isDir())
315
- {
316
- return $this->processDirectory($content->getRealPath());
317
- }
318
-
319
- // Delete file
320
- if ($content->isFile())
321
- {
322
- @unlink($content->getRealPath());
323
- }
324
- }
325
-
326
- // Delete directory
327
- $this->job->lastDeletedDirectory = realpath($path . "/..");
328
- @rmdir($path);
329
- $this->updateJob();
330
- $this->processDirectory($this->job->nextDirectoryToDelete);
331
- }
332
-
333
- /**
334
- * @param string $path
335
- * @return bool
336
- */
337
- private function shouldStop($path)
338
- {
339
- // Just to make sure the root dir is never deleted!
340
- if ($path === get_home_path()){
341
- $this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
342
- return true;
343
- }
344
-
345
- // Check if threshold is reached and is valid dir
346
- return (
347
- $this->isOverThreshold() ||
348
- !is_dir($path) ||
349
- $this->isDirectoryDeletingFinished()
350
- );
351
- }
352
-
353
- /**
354
- * Finish / Update Existing Clones
355
- */
356
- public function deleteFinish()
357
- {
358
- $existingClones = get_option("wpstg_existing_clones_beta", array());
359
-
360
- // Check if clones still exist
361
- $this->log("Verifying existing clones...");
362
- foreach ($existingClones as $name => $clone)
363
- {
364
- if (!is_dir($clone["path"]))
365
- {
366
- unset($existingClones[$name]);
367
- }
368
- }
369
- $this->log("Existing clones verified!");
370
-
371
- if (false === update_option("wpstg_existing_clones_beta", $existingClones))
372
- {
373
- $this->log("Failed to save {$this->options->clone}'s clone job data to database'");
374
- }
375
-
376
- // Delete cached file
377
- $this->cache->delete("delete_job_{$this->clone->name}");
378
- $this->cache->delete("delete_directories_{$this->clone->name}");
379
-
380
- return true;
381
- }
382
- }
apps/Backend/Modules/Jobs/Delete_old.php CHANGED
@@ -10,7 +10,7 @@ use WPStaging\WPStaging;
10
* Class Delete
11
* @package WPStaging\Backend\Modules\Jobs
12
*/
13
- class Delete_old extends Job
14
{
15
16
/**
10
* Class Delete
11
* @package WPStaging\Backend\Modules\Jobs
12
*/
13
+ class Delete extends Job
14
{
15
16
/**
apps/Backend/Modules/Jobs/Directories.php CHANGED
@@ -203,20 +203,10 @@ class Directories extends JobExecutable {
203
* @return string|false
204
*/
205
protected function getPath( $directory ) {
206
-
207
- /*
208
- * Do not follow root path like src/web/..
209
- * This must be done before \SplFileInfo->isDir() is used!
210
- * Prevents open base dir restriction fatal errors
211
- */
212
- if (strpos( $directory->getRealPath(), ABSPATH ) !== 0 ) {
213
- return false;
214
- }
215
-
216
$path = str_replace( ABSPATH, null, $directory->getRealPath() );
217
218
// Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
219
- if( !$directory->isDir() || strlen( $path ) < 1 ) {
220
return false;
221
}
222
@@ -277,7 +267,7 @@ class Directories extends JobExecutable {
277
protected function getFiles() {
278
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
279
280
- if( false === ($this->files = @file_get_contents( $fileName )) ) {
281
$this->files = array();
282
return;
283
}
203
* @return string|false
204
*/
205
protected function getPath( $directory ) {
206
$path = str_replace( ABSPATH, null, $directory->getRealPath() );
207
208
// Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
209
+ if( !$directory->isDir() || strlen( $path ) < 1 || strpos( $directory->getRealPath(), ABSPATH ) !== 0 ) {
210
return false;
211
}
212
267
protected function getFiles() {
268
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
269
270
+ if( false === ($this->files = file_get_contents( $fileName )) ) {
271
$this->files = array();
272
return;