Version Description
Download this release
Release Info
Developer | danielbachhuber |
Plugin | The WP Remote WordPress Plugin |
Version | 2.7.0 |
Comparing to | |
See all releases |
Code changes from version 2.6.7 to 2.7.0
- .travis.yml +2 -2
- plugin.php +32 -3
- readme.txt +9 -2
- wprp.api.php +357 -18
- wprp.backups.php +222 -43
- wprp.hm.backup.php +540 -15
- wprp.integration.php +16 -0
- wprp.plugins.php +107 -23
- wprp.themes.php +27 -15
.travis.yml
CHANGED
@@ -18,10 +18,10 @@ env:
|
|
18 |
- WP_VERSION=3.2 WP_MULTISITE=1
|
19 |
|
20 |
notifications:
|
21 |
-
|
22 |
|
23 |
before_script:
|
24 |
- export WP_TESTS_DIR=/tmp/wordpress-tests/
|
25 |
-
- bash bin/install-wp-tests.sh wordpress_test root '' $WP_VERSION
|
26 |
|
27 |
script: phpunit
|
18 |
- WP_VERSION=3.2 WP_MULTISITE=1
|
19 |
|
20 |
notifications:
|
21 |
+
secure: "gwybVEhn3tYVngWMegtYJ0dfSBjLa1+0LsD9LXypHtyMjkUBuoEu0NWkupkp4HA27Euq5Cryg01vhWhy7+8kUIFeSnkYDqcvIHduPvyYqSwaZFNEgINZ/2OiQOomg23C+/sYxqzmXeFiRChHvR26/9FfhLSDqvGPZ4/n/URRFgg="
|
22 |
|
23 |
before_script:
|
24 |
- export WP_TESTS_DIR=/tmp/wordpress-tests/
|
25 |
+
- bash bin/install-wp-tests.sh wordpress_test root '' $WP_VERSION
|
26 |
|
27 |
script: phpunit
|
plugin.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
/*
|
4 |
Plugin Name: WP Remote
|
5 |
Description: Manage your WordPress site with <a href="https://wpremote.com/">WP Remote</a>. <strong>Deactivate to clear your API Key.</strong>
|
6 |
-
Version: 2.
|
7 |
Author: Human Made Limited
|
8 |
Author URI: http://hmn.md/
|
9 |
*/
|
@@ -88,6 +88,7 @@ function wprp_catch_api_call() {
|
|
88 |
if ( empty( $_POST['wpr_verify_key'] ) )
|
89 |
return;
|
90 |
|
|
|
91 |
require_once( WPRP_PLUGIN_PATH . '/wprp.plugins.php' );
|
92 |
require_once( WPRP_PLUGIN_PATH . '/wprp.themes.php' );
|
93 |
|
@@ -96,7 +97,32 @@ function wprp_catch_api_call() {
|
|
96 |
exit;
|
97 |
|
98 |
}
|
99 |
-
add_action( 'init', 'wprp_catch_api_call',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
/**
|
102 |
* Get the stored WPR API key
|
@@ -162,6 +188,9 @@ function wprp_update() {
|
|
162 |
|
163 |
function _wprp_upgrade_core() {
|
164 |
|
|
|
|
|
|
|
165 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
166 |
include_once ( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
167 |
include_once ( ABSPATH . 'wp-includes/update.php' );
|
@@ -170,7 +199,7 @@ function _wprp_upgrade_core() {
|
|
170 |
|
171 |
// check for filesystem access
|
172 |
if ( ! _wpr_check_filesystem_access() )
|
173 |
-
return
|
174 |
|
175 |
// force refresh
|
176 |
wp_version_check();
|
3 |
/*
|
4 |
Plugin Name: WP Remote
|
5 |
Description: Manage your WordPress site with <a href="https://wpremote.com/">WP Remote</a>. <strong>Deactivate to clear your API Key.</strong>
|
6 |
+
Version: 2.7.0
|
7 |
Author: Human Made Limited
|
8 |
Author URI: http://hmn.md/
|
9 |
*/
|
88 |
if ( empty( $_POST['wpr_verify_key'] ) )
|
89 |
return;
|
90 |
|
91 |
+
require_once( WPRP_PLUGIN_PATH . '/wprp.integration.php' );
|
92 |
require_once( WPRP_PLUGIN_PATH . '/wprp.plugins.php' );
|
93 |
require_once( WPRP_PLUGIN_PATH . '/wprp.themes.php' );
|
94 |
|
97 |
exit;
|
98 |
|
99 |
}
|
100 |
+
add_action( 'init', 'wprp_catch_api_call', 100 );
|
101 |
+
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Check for a bat signal from the mothership
|
105 |
+
*
|
106 |
+
* @since 2.7.0
|
107 |
+
*/
|
108 |
+
function wprp_check_bat_signal() {
|
109 |
+
|
110 |
+
$bat_signal_key = 'wprp_bat_signal';
|
111 |
+
|
112 |
+
if ( false === get_transient( $bat_signal_key ) ) {
|
113 |
+
|
114 |
+
$bat_signal_url = trailingslashit( WPR_URL ) . 'bat-signal/';
|
115 |
+
$response = wp_remote_get( $bat_signal_url );
|
116 |
+
$response_body = wp_remote_retrieve_body( $response );
|
117 |
+
if ( 'destroy the evidence!' == trim( $response_body ) )
|
118 |
+
delete_option( 'wpr_api_key' );
|
119 |
+
|
120 |
+
// One request per day
|
121 |
+
set_transient( $bat_signal_key, 'the coast is clear', 60 * 60 * 24 );
|
122 |
+
}
|
123 |
+
|
124 |
+
}
|
125 |
+
add_action( 'init', 'wprp_check_bat_signal' );
|
126 |
|
127 |
/**
|
128 |
* Get the stored WPR API key
|
188 |
|
189 |
function _wprp_upgrade_core() {
|
190 |
|
191 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
192 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
193 |
+
|
194 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
195 |
include_once ( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
196 |
include_once ( ABSPATH . 'wp-includes/update.php' );
|
199 |
|
200 |
// check for filesystem access
|
201 |
if ( ! _wpr_check_filesystem_access() )
|
202 |
+
return new WP_Error( 'filesystem-not-writable', __( 'The filesystem is not writable with the supplied credentials', 'wpremote' ) );
|
203 |
|
204 |
// force refresh
|
205 |
wp_version_check();
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: humanmade, willmot, joehoyle, danielbachhuber, mattheu, pauldewouters, cuvelier, tcrsavage
|
3 |
Tags: wpremote, remote administration, multiple wordpress
|
4 |
Requires at least: 3.0
|
5 |
-
Tested up to: 3.7
|
6 |
-
Stable tag: 2.
|
7 |
|
8 |
WP Remote is a free web app that enables you to easily manage all of your WordPress powered sites from one place.
|
9 |
|
@@ -37,6 +37,13 @@ You can email us at support@wpremote.com for support.
|
|
37 |
|
38 |
== Changelog ==
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
#### 2.6.7 (27 October 2013)
|
41 |
|
42 |
* API improvement: specify database- and file-only backups
|
2 |
Contributors: humanmade, willmot, joehoyle, danielbachhuber, mattheu, pauldewouters, cuvelier, tcrsavage
|
3 |
Tags: wpremote, remote administration, multiple wordpress
|
4 |
Requires at least: 3.0
|
5 |
+
Tested up to: 3.7.1
|
6 |
+
Stable tag: 2.7.0
|
7 |
|
8 |
WP Remote is a free web app that enables you to easily manage all of your WordPress powered sites from one place.
|
9 |
|
37 |
|
38 |
== Changelog ==
|
39 |
|
40 |
+
#### 2.7.0 (19 November 2013)
|
41 |
+
|
42 |
+
* Improved durability of backups where the backup process can take more than 90 seconds.
|
43 |
+
* New API support for posts, comments, and fixed support for users (oops).
|
44 |
+
* Reporting and update integration with premium plugins that support ManageWP's API implementation.
|
45 |
+
* Plugin, theme, and core updates now respect the `DISALLOW_FILE_MODS` constant.
|
46 |
+
|
47 |
#### 2.6.7 (27 October 2013)
|
48 |
|
49 |
* API improvement: specify database- and file-only backups
|
wprp.api.php
CHANGED
@@ -65,7 +65,7 @@ class WPR_API_Request {
|
|
65 |
}
|
66 |
|
67 |
static function get_arg( $arg ) {
|
68 |
-
return ( isset( self::$args[$arg] ) ) ? self::$args[$arg] :
|
69 |
}
|
70 |
}
|
71 |
|
@@ -79,6 +79,10 @@ if ( class_exists( 'WPRP_Log' ) )
|
|
79 |
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG )
|
80 |
error_reporting( 0 );
|
81 |
|
|
|
|
|
|
|
|
|
82 |
// Log in as admin
|
83 |
// TODO what about if admin use doesn't exists?
|
84 |
wp_set_current_user( 1 );
|
@@ -129,6 +133,23 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
129 |
|
130 |
break;
|
131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
case 'upgrade_core' :
|
133 |
|
134 |
$actions[$action] = _wprp_upgrade_core();
|
@@ -144,34 +165,37 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
144 |
case 'update_plugin' :
|
145 |
case 'upgrade_plugin' :
|
146 |
|
147 |
-
$
|
|
|
|
|
|
|
148 |
|
149 |
break;
|
150 |
|
151 |
case 'install_plugin' :
|
152 |
|
153 |
$api_args = array(
|
154 |
-
'version' => sanitize_text_field(
|
155 |
);
|
156 |
-
$actions[$action] = _wprp_install_plugin(
|
157 |
|
158 |
break;
|
159 |
|
160 |
case 'activate_plugin' :
|
161 |
|
162 |
-
$actions[$action] = _wprp_activate_plugin(
|
163 |
|
164 |
break;
|
165 |
|
166 |
case 'deactivate_plugin' :
|
167 |
|
168 |
-
$actions[$action] = _wprp_deactivate_plugin(
|
169 |
|
170 |
break;
|
171 |
|
172 |
case 'uninstall_plugin' :
|
173 |
|
174 |
-
$actions[$action] = _wprp_uninstall_plugin(
|
175 |
|
176 |
break;
|
177 |
|
@@ -184,28 +208,28 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
184 |
case 'install_theme':
|
185 |
|
186 |
$api_args = array(
|
187 |
-
'version' => sanitize_text_field(
|
188 |
);
|
189 |
-
$actions[$action] = _wprp_install_theme(
|
190 |
|
191 |
break;
|
192 |
|
193 |
case 'activate_theme':
|
194 |
|
195 |
-
$actions[$action] = _wprp_activate_theme(
|
196 |
|
197 |
break;
|
198 |
|
199 |
case 'update_theme' :
|
200 |
case 'upgrade_theme' : // 'upgrade' is deprecated
|
201 |
|
202 |
-
$actions[$action] = _wprp_update_theme(
|
203 |
|
204 |
break;
|
205 |
|
206 |
case 'delete_theme':
|
207 |
|
208 |
-
$actions[$action] = _wprp_delete_theme(
|
209 |
|
210 |
break;
|
211 |
|
@@ -214,6 +238,9 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
214 |
if ( in_array( WPR_API_Request::get_arg( 'backup_type' ), array( 'complete', 'database', 'file' ) ) )
|
215 |
WPRP_Backups::get_instance()->set_type( WPR_API_Request::get_arg( 'backup_type' ) );
|
216 |
|
|
|
|
|
|
|
217 |
$actions[$action] = WPRP_Backups::get_instance()->do_backup();
|
218 |
|
219 |
break;
|
@@ -230,6 +257,17 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
230 |
|
231 |
break;
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
case 'supports_backups' :
|
234 |
|
235 |
$actions[$action] = true;
|
@@ -242,7 +280,8 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
242 |
'site_url' => get_site_url(),
|
243 |
'home_url' => get_home_url(),
|
244 |
'admin_url' => get_admin_url(),
|
245 |
-
'backups' => function_exists( '_wprp_get_backups_info' ) ? _wprp_get_backups_info() : array()
|
|
|
246 |
);
|
247 |
|
248 |
break;
|
@@ -265,6 +304,256 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
265 |
|
266 |
break;
|
267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
case 'get_users':
|
269 |
|
270 |
$arg_keys = array(
|
@@ -288,6 +577,58 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
288 |
|
289 |
break;
|
290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
case 'create_user':
|
292 |
|
293 |
$args = array(
|
@@ -301,14 +642,12 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
301 |
);
|
302 |
foreach( $args as $key => $value ) {
|
303 |
// Note: wp_insert_user() handles sanitization / validation
|
304 |
-
if ( $new_value = WPR_API_Request::get_arg( $key ) )
|
305 |
$args[$key] = $new_value;
|
306 |
}
|
307 |
|
308 |
if ( ! $args['user_pass'] ) {
|
309 |
-
$args['user_pass'] =
|
310 |
-
} else {
|
311 |
-
$generated_password = false;
|
312 |
}
|
313 |
|
314 |
$user_id = wp_insert_user( $args );
|
@@ -316,7 +655,7 @@ foreach( WPR_API_Request::get_actions() as $action ) {
|
|
316 |
if ( is_wp_error( $user_id ) ) {
|
317 |
$actions[$action] = array( 'status' => 'error', 'error' => $user_id->get_error_message() );
|
318 |
} else {
|
319 |
-
$actions[$action] =
|
320 |
}
|
321 |
|
322 |
break;
|
65 |
}
|
66 |
|
67 |
static function get_arg( $arg ) {
|
68 |
+
return ( isset( self::$args[$arg] ) ) ? self::$args[$arg] : null;
|
69 |
}
|
70 |
}
|
71 |
|
79 |
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG )
|
80 |
error_reporting( 0 );
|
81 |
|
82 |
+
// Temp hack so our requests to verify file size are signed.
|
83 |
+
global $wprp_noauth_nonce;
|
84 |
+
$wprp_noauth_nonce = wp_create_nonce( 'wprp_calculate_backup_size' );
|
85 |
+
|
86 |
// Log in as admin
|
87 |
// TODO what about if admin use doesn't exists?
|
88 |
wp_set_current_user( 1 );
|
133 |
|
134 |
break;
|
135 |
|
136 |
+
case 'get_constants':
|
137 |
+
|
138 |
+
$constants = array();
|
139 |
+
if ( is_array( WPR_API_Request::get_arg( 'constants' ) ) ) {
|
140 |
+
|
141 |
+
foreach( WPR_API_Request::get_arg( 'constants' ) as $constant ) {
|
142 |
+
if ( defined( $constant ) )
|
143 |
+
$constants[$constant] = constant( $constant );
|
144 |
+
else
|
145 |
+
$constants[$constant] = null;
|
146 |
+
}
|
147 |
+
|
148 |
+
}
|
149 |
+
$actions[$action] = $constants;
|
150 |
+
|
151 |
+
break;
|
152 |
+
|
153 |
case 'upgrade_core' :
|
154 |
|
155 |
$actions[$action] = _wprp_upgrade_core();
|
165 |
case 'update_plugin' :
|
166 |
case 'upgrade_plugin' :
|
167 |
|
168 |
+
$api_args = array(
|
169 |
+
'zip_url' => esc_url_raw( WPR_API_Request::get_arg( 'zip_url' ) ),
|
170 |
+
);
|
171 |
+
$actions[$action] = _wprp_update_plugin( sanitize_text_field( WPR_API_Request::get_arg( 'plugin' ) ), $api_args );
|
172 |
|
173 |
break;
|
174 |
|
175 |
case 'install_plugin' :
|
176 |
|
177 |
$api_args = array(
|
178 |
+
'version' => sanitize_text_field( WPR_API_Request::get_arg( 'version' ) ),
|
179 |
);
|
180 |
+
$actions[$action] = _wprp_install_plugin( sanitize_text_field( WPR_API_Request::get_arg( 'plugin' ) ), $api_args );
|
181 |
|
182 |
break;
|
183 |
|
184 |
case 'activate_plugin' :
|
185 |
|
186 |
+
$actions[$action] = _wprp_activate_plugin( sanitize_text_field( WPR_API_Request::get_arg( 'plugin' ) ) );
|
187 |
|
188 |
break;
|
189 |
|
190 |
case 'deactivate_plugin' :
|
191 |
|
192 |
+
$actions[$action] = _wprp_deactivate_plugin( sanitize_text_field( WPR_API_Request::get_arg( 'plugin' ) ) );
|
193 |
|
194 |
break;
|
195 |
|
196 |
case 'uninstall_plugin' :
|
197 |
|
198 |
+
$actions[$action] = _wprp_uninstall_plugin( sanitize_text_field( WPR_API_Request::get_arg( 'plugin' ) ) );
|
199 |
|
200 |
break;
|
201 |
|
208 |
case 'install_theme':
|
209 |
|
210 |
$api_args = array(
|
211 |
+
'version' => sanitize_text_field( WPR_API_Request::get_arg( 'version' ) ),
|
212 |
);
|
213 |
+
$actions[$action] = _wprp_install_theme( sanitize_text_field( WPR_API_Request::get_arg( 'theme' ) ), $api_args );
|
214 |
|
215 |
break;
|
216 |
|
217 |
case 'activate_theme':
|
218 |
|
219 |
+
$actions[$action] = _wprp_activate_theme( sanitize_text_field( WPR_API_Request::get_arg( 'theme' ) ) );
|
220 |
|
221 |
break;
|
222 |
|
223 |
case 'update_theme' :
|
224 |
case 'upgrade_theme' : // 'upgrade' is deprecated
|
225 |
|
226 |
+
$actions[$action] = _wprp_update_theme( sanitize_text_field( WPR_API_Request::get_arg( 'theme' ) ) );
|
227 |
|
228 |
break;
|
229 |
|
230 |
case 'delete_theme':
|
231 |
|
232 |
+
$actions[$action] = _wprp_delete_theme( sanitize_text_field( WPR_API_Request::get_arg( 'theme' ) ) );
|
233 |
|
234 |
break;
|
235 |
|
238 |
if ( in_array( WPR_API_Request::get_arg( 'backup_type' ), array( 'complete', 'database', 'file' ) ) )
|
239 |
WPRP_Backups::get_instance()->set_type( WPR_API_Request::get_arg( 'backup_type' ) );
|
240 |
|
241 |
+
if ( WPR_API_Request::get_arg( 'backup_approach' ) && 'file_manifest' == WPR_API_Request::get_arg( 'backup_approach' ) )
|
242 |
+
WPRP_Backups::get_instance()->set_is_using_file_manifest( true );
|
243 |
+
|
244 |
$actions[$action] = WPRP_Backups::get_instance()->do_backup();
|
245 |
|
246 |
break;
|
257 |
|
258 |
break;
|
259 |
|
260 |
+
case 'backup_heartbeat' :
|
261 |
+
|
262 |
+
WPRP_Backups::get_instance()->set_is_using_file_manifest( true );
|
263 |
+
|
264 |
+
if ( in_array( WPR_API_Request::get_arg( 'backup_type' ), array( 'complete', 'database', 'file' ) ) )
|
265 |
+
WPRP_Backups::get_instance()->set_type( WPR_API_Request::get_arg( 'backup_type' ) );
|
266 |
+
|
267 |
+
$actions[$action] = WPRP_Backups::get_instance()->backup_heartbeat();
|
268 |
+
|
269 |
+
break;
|
270 |
+
|
271 |
case 'supports_backups' :
|
272 |
|
273 |
$actions[$action] = true;
|
280 |
'site_url' => get_site_url(),
|
281 |
'home_url' => get_home_url(),
|
282 |
'admin_url' => get_admin_url(),
|
283 |
+
'backups' => function_exists( '_wprp_get_backups_info' ) ? _wprp_get_backups_info() : array(),
|
284 |
+
'web_host' => _wprp_integration_get_web_host(),
|
285 |
);
|
286 |
|
287 |
break;
|
304 |
|
305 |
break;
|
306 |
|
307 |
+
case 'get_posts':
|
308 |
+
|
309 |
+
$arg_keys = array(
|
310 |
+
/** Author **/
|
311 |
+
'author',
|
312 |
+
'author_name',
|
313 |
+
'author__in',
|
314 |
+
'author__not_in',
|
315 |
+
|
316 |
+
/** Category **/
|
317 |
+
'cat',
|
318 |
+
'category_name',
|
319 |
+
'category__and',
|
320 |
+
'category__in',
|
321 |
+
'category__not_in',
|
322 |
+
|
323 |
+
/** Tag **/
|
324 |
+
'tag',
|
325 |
+
'tag_id',
|
326 |
+
'tag__and',
|
327 |
+
'tag__in',
|
328 |
+
'tag__not_in',
|
329 |
+
'tag_slug__and',
|
330 |
+
'tag_slug__in',
|
331 |
+
|
332 |
+
/** Search **/
|
333 |
+
's',
|
334 |
+
|
335 |
+
/** Post Attributes **/
|
336 |
+
'name',
|
337 |
+
'pagename',
|
338 |
+
'post_parent',
|
339 |
+
'post_parent__in',
|
340 |
+
'post_parent__not_in',
|
341 |
+
'post__in',
|
342 |
+
'post__not_in',
|
343 |
+
'post_status',
|
344 |
+
'post_type',
|
345 |
+
|
346 |
+
/** Order / Pagination / Etc. **/
|
347 |
+
'order',
|
348 |
+
'orderby',
|
349 |
+
'nopaging',
|
350 |
+
'posts_per_page',
|
351 |
+
'offset',
|
352 |
+
'paged',
|
353 |
+
'page',
|
354 |
+
'ignore_sticky_posts',
|
355 |
+
);
|
356 |
+
$args = array();
|
357 |
+
foreach( $arg_keys as $arg_key ) {
|
358 |
+
// Note: WP_Query() supports validation / sanitization
|
359 |
+
if ( null !== ( $value = WPR_API_Request::get_arg( $arg_key ) ) )
|
360 |
+
$args[$arg_key] = $value;
|
361 |
+
}
|
362 |
+
|
363 |
+
$query = new WP_Query;
|
364 |
+
$query->query( $args );
|
365 |
+
$actions[$action] = $query->posts;
|
366 |
+
|
367 |
+
break;
|
368 |
+
|
369 |
+
case 'get_post':
|
370 |
+
case 'delete_post':
|
371 |
+
|
372 |
+
$post_id = (int)WPR_API_Request::get_arg( 'post_id' );
|
373 |
+
$post = get_post( $post_id );
|
374 |
+
|
375 |
+
if ( ! $post ) {
|
376 |
+
$actions[$action] = new WP_Error( 'missing-post', __( "No post found.", 'wpremote' ) );
|
377 |
+
break;
|
378 |
+
}
|
379 |
+
|
380 |
+
if ( 'get_post' == $action ) {
|
381 |
+
|
382 |
+
$actions[$action] = $post;
|
383 |
+
|
384 |
+
} else if ( 'delete_post' == $action ) {
|
385 |
+
|
386 |
+
$actions[$action] = wp_delete_post( $post_id );
|
387 |
+
|
388 |
+
}
|
389 |
+
|
390 |
+
break;
|
391 |
+
|
392 |
+
case 'create_post':
|
393 |
+
case 'update_post':
|
394 |
+
|
395 |
+
$arg_keys = array(
|
396 |
+
'menu_order',
|
397 |
+
'comment_status',
|
398 |
+
'ping_status',
|
399 |
+
'post_author',
|
400 |
+
'post_content',
|
401 |
+
'post_date',
|
402 |
+
'post_date_gmt',
|
403 |
+
'post_excerpt',
|
404 |
+
'post_name',
|
405 |
+
'post_parent',
|
406 |
+
'post_password',
|
407 |
+
'post_status',
|
408 |
+
'post_title',
|
409 |
+
'post_type',
|
410 |
+
'tags_input',
|
411 |
+
);
|
412 |
+
$args = array();
|
413 |
+
foreach( $arg_keys as $arg_key ) {
|
414 |
+
// Note: wp_update_post() supports validation / sanitization
|
415 |
+
if ( null !== ( $value = WPR_API_Request::get_arg( $arg_key ) ) )
|
416 |
+
$args[$arg_key] = $value;
|
417 |
+
}
|
418 |
+
|
419 |
+
if ( 'create_post' == $action ) {
|
420 |
+
|
421 |
+
if ( $post_id = wp_insert_post( $args ) )
|
422 |
+
$actions[$action] = get_post( $post_id );
|
423 |
+
else
|
424 |
+
$actions[$action] = new WP_Error( 'create-post', __( "Error creating post.", 'wpremote' ) );
|
425 |
+
|
426 |
+
} else if ( 'update_post' == $action ) {
|
427 |
+
|
428 |
+
$args['ID'] = (int)WPR_API_Request::get_arg( 'post_id' );
|
429 |
+
|
430 |
+
if ( ! get_post( $args['ID'] ) ) {
|
431 |
+
$actions[$action] = new WP_Error( 'missing-post', __( "No post found.", 'wpremote' ) );
|
432 |
+
break;
|
433 |
+
}
|
434 |
+
|
435 |
+
if ( wp_update_post( $args ) )
|
436 |
+
$actions[$action] = get_post( $args['ID'] );
|
437 |
+
else
|
438 |
+
$actions[$action] = new WP_Error( 'update-post', __( "Error updating post.", 'wpremote' ) );
|
439 |
+
|
440 |
+
}
|
441 |
+
|
442 |
+
break;
|
443 |
+
|
444 |
+
case 'get_metadata':
|
445 |
+
|
446 |
+
$actions[$action] = get_metadata( WPR_API_Request::get_arg( 'meta_type' ), WPR_API_Request::get_arg( 'object_id' ), WPR_API_Request::get_arg( 'meta_key' ), false );
|
447 |
+
|
448 |
+
break;
|
449 |
+
|
450 |
+
case 'add_metadata':
|
451 |
+
|
452 |
+
$actions[$action] = add_metadata( WPR_API_Request::get_arg( 'meta_type' ), WPR_API_Request::get_arg( 'object_id' ), WPR_API_Request::get_arg( 'meta_key' ), WPR_API_Request::get_arg( 'meta_value' ) );
|
453 |
+
|
454 |
+
break;
|
455 |
+
|
456 |
+
case 'update_metadata':
|
457 |
+
|
458 |
+
$actions[$action] = update_metadata( WPR_API_Request::get_arg( 'meta_type' ), WPR_API_Request::get_arg( 'object_id' ), WPR_API_Request::get_arg( 'meta_key' ), WPR_API_Request::get_arg( 'meta_value' ) );
|
459 |
+
|
460 |
+
break;
|
461 |
+
|
462 |
+
case 'delete_metadata':
|
463 |
+
|
464 |
+
$actions[$action] = delete_metadata( WPR_API_Request::get_arg( 'meta_type' ), WPR_API_Request::get_arg( 'object_id' ), WPR_API_Request::get_arg( 'meta_key' ) );
|
465 |
+
|
466 |
+
break;
|
467 |
+
|
468 |
+
case 'get_comments':
|
469 |
+
|
470 |
+
$arg_keys = array(
|
471 |
+
'status',
|
472 |
+
'orderby',
|
473 |
+
'order',
|
474 |
+
'post_id',
|
475 |
+
);
|
476 |
+
$args = array();
|
477 |
+
foreach( $arg_keys as $arg_key ) {
|
478 |
+
// Note: get_comments() supports validation / sanitization
|
479 |
+
if ( null !== ( $value = WPR_API_Request::get_arg( $arg_key ) ) )
|
480 |
+
$args[$arg_key] = $value;
|
481 |
+
}
|
482 |
+
$actions[$action] = get_comments( $args );
|
483 |
+
|
484 |
+
break;
|
485 |
+
|
486 |
+
case 'get_comment':
|
487 |
+
case 'delete_comment':
|
488 |
+
|
489 |
+
$comment_id = (int)WPR_API_Request::get_arg( 'comment_id' );
|
490 |
+
$comment = get_comment( $comment_id );
|
491 |
+
|
492 |
+
if ( ! $comment ) {
|
493 |
+
$actions[$action] = new WP_Error( 'missing-comment', __( "No comment found.", 'wpremote' ) );
|
494 |
+
break;
|
495 |
+
}
|
496 |
+
|
497 |
+
if ( 'get_comment' == $action ) {
|
498 |
+
|
499 |
+
$actions[$action] = $comment;
|
500 |
+
|
501 |
+
} else if ( 'delete_comment' == $action ) {
|
502 |
+
|
503 |
+
$actions[$action] = wp_delete_comment( $comment_id );
|
504 |
+
|
505 |
+
}
|
506 |
+
|
507 |
+
break;
|
508 |
+
|
509 |
+
case 'create_comment':
|
510 |
+
case 'update_comment':
|
511 |
+
|
512 |
+
$arg_keys = array(
|
513 |
+
'comment_post_ID',
|
514 |
+
'comment_author',
|
515 |
+
'comment_author_email',
|
516 |
+
'comment_author_url',
|
517 |
+
'comment_date',
|
518 |
+
'comment_date_gmt',
|
519 |
+
'comment_content',
|
520 |
+
'comment_approved',
|
521 |
+
'comment_type',
|
522 |
+
'comment_parent',
|
523 |
+
'user_id'
|
524 |
+
);
|
525 |
+
$args = array();
|
526 |
+
foreach( $arg_keys as $arg_key ) {
|
527 |
+
// Note: wp_update_comment() supports validation / sanitization
|
528 |
+
if ( null !== ( $value = WPR_API_Request::get_arg( $arg_key ) ) )
|
529 |
+
$args[$arg_key] = $value;
|
530 |
+
}
|
531 |
+
|
532 |
+
if ( 'create_comment' == $action ) {
|
533 |
+
|
534 |
+
if ( $comment_id = wp_insert_comment( $args ) )
|
535 |
+
$actions[$action] = get_comment( $comment_id );
|
536 |
+
else
|
537 |
+
$actions[$action] = new WP_Error( 'create-comment', __( "Error creating comment.", 'wpremote' ) );
|
538 |
+
|
539 |
+
} else if ( 'update_comment' == $action ) {
|
540 |
+
|
541 |
+
$args['comment_ID'] = (int)WPR_API_Request::get_arg( 'comment_id' );
|
542 |
+
|
543 |
+
if ( ! get_comment( $args['comment_ID'] ) ) {
|
544 |
+
$actions[$action] = new WP_Error( 'missing-comment', __( "No comment found.", 'wpremote' ) );
|
545 |
+
break;
|
546 |
+
}
|
547 |
+
|
548 |
+
if ( wp_update_comment( $args ) )
|
549 |
+
$actions[$action] = get_comment( $args['comment_ID'] );
|
550 |
+
else
|
551 |
+
$actions[$action] = new WP_Error( 'update-comment', __( "Error updating comment.", 'wpremote' ) );
|
552 |
+
|
553 |
+
}
|
554 |
+
|
555 |
+
break;
|
556 |
+
|
557 |
case 'get_users':
|
558 |
|
559 |
$arg_keys = array(
|
577 |
|
578 |
break;
|
579 |
|
580 |
+
case 'get_user':
|
581 |
+
case 'update_user':
|
582 |
+
case 'delete_user':
|
583 |
+
|
584 |
+
$user_id = (int)WPR_API_Request::get_arg( 'user_id' );
|
585 |
+
$user = get_user_by( 'id', $user_id );
|
586 |
+
|
587 |
+
if ( ! $user ) {
|
588 |
+
$actions[$action] = new WP_Error( 'missing-user', "No user found." );
|
589 |
+
break;
|
590 |
+
}
|
591 |
+
|
592 |
+
require_once ABSPATH . '/wp-admin/includes/user.php';
|
593 |
+
|
594 |
+
if ( 'get_user' == $action ) {
|
595 |
+
|
596 |
+
$actions[$action] = wprp_format_user_obj( $user );
|
597 |
+
|
598 |
+
} else if ( 'update_user' == $action ) {
|
599 |
+
|
600 |
+
$fields = array(
|
601 |
+
'user_email',
|
602 |
+
'display_name',
|
603 |
+
'first_name',
|
604 |
+
'last_name',
|
605 |
+
'user_nicename',
|
606 |
+
'user_pass',
|
607 |
+
'user_url',
|
608 |
+
'description'
|
609 |
+
);
|
610 |
+
$args = array();
|
611 |
+
foreach( $fields as $field ) {
|
612 |
+
// Note: wp_update_user() handles sanitization / validation
|
613 |
+
if ( null !== ( $value = WPR_API_Request::get_arg( $field ) ) )
|
614 |
+
$args[$field] = $value;
|
615 |
+
}
|
616 |
+
$args['ID'] = $user->ID;
|
617 |
+
$ret = wp_update_user( $args );
|
618 |
+
if ( is_wp_error( $ret ) )
|
619 |
+
$actions[$action] = $ret;
|
620 |
+
else
|
621 |
+
$actions[$action] = wprp_format_user_obj( get_user_by( 'id', $ret ) );
|
622 |
+
|
623 |
+
} else if ( 'delete_user' == $action ) {
|
624 |
+
|
625 |
+
$actions[$action] = wp_delete_user( $user->ID );
|
626 |
+
|
627 |
+
}
|
628 |
+
|
629 |
+
|
630 |
+
break;
|
631 |
+
|
632 |
case 'create_user':
|
633 |
|
634 |
$args = array(
|
642 |
);
|
643 |
foreach( $args as $key => $value ) {
|
644 |
// Note: wp_insert_user() handles sanitization / validation
|
645 |
+
if ( null !== ( $new_value = WPR_API_Request::get_arg( $key ) ) )
|
646 |
$args[$key] = $new_value;
|
647 |
}
|
648 |
|
649 |
if ( ! $args['user_pass'] ) {
|
650 |
+
$args['user_pass'] = wp_generate_password();
|
|
|
|
|
651 |
}
|
652 |
|
653 |
$user_id = wp_insert_user( $args );
|
655 |
if ( is_wp_error( $user_id ) ) {
|
656 |
$actions[$action] = array( 'status' => 'error', 'error' => $user_id->get_error_message() );
|
657 |
} else {
|
658 |
+
$actions[$action] = wprp_format_user_obj( get_user_by( 'id', $user_id ) );
|
659 |
}
|
660 |
|
661 |
break;
|
wprp.backups.php
CHANGED
@@ -23,41 +23,13 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
23 |
*/
|
24 |
public static function get_instance() {
|
25 |
|
26 |
-
if ( empty( self::$instance ) )
|
27 |
self::$instance = new WPRP_Backups();
|
28 |
-
|
29 |
-
return self::$instance;
|
30 |
-
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Recursively delete a directory including
|
35 |
-
* all the files and sub-directories.
|
36 |
-
*
|
37 |
-
* @param string $dir
|
38 |
-
* @return bool
|
39 |
-
*/
|
40 |
-
public static function rmdir_recursive( $dir ) {
|
41 |
-
|
42 |
-
if ( is_file( $dir ) )
|
43 |
-
@unlink( $dir );
|
44 |
-
|
45 |
-
if ( ! is_dir( $dir ) )
|
46 |
-
return false;
|
47 |
-
|
48 |
-
$files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
|
49 |
-
|
50 |
-
foreach ( $files as $file ) {
|
51 |
-
|
52 |
-
if ( $file->isDir() )
|
53 |
-
@rmdir( $file->getPathname() );
|
54 |
-
|
55 |
-
else
|
56 |
-
@unlink( $file->getPathname() );
|
57 |
|
58 |
}
|
59 |
|
60 |
-
|
61 |
|
62 |
}
|
63 |
|
@@ -74,9 +46,12 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
74 |
|
75 |
// Set the excludes
|
76 |
if ( class_exists( 'WPR_API_Request' ) && WPR_API_Request::get_arg( 'backup_excludes' ) )
|
77 |
-
$
|
78 |
else if ( isset( $_GET['backup_excludes'] ) )
|
79 |
-
$
|
|
|
|
|
|
|
80 |
|
81 |
$this->filesize_transient = 'wprp_' . '_' . $this->get_type() . '_' . substr( md5( $this->exclude_string() ), 20 ) . '_filesize';
|
82 |
|
@@ -92,10 +67,19 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
92 |
|
93 |
$this->set_status( 'Starting backup...' );
|
94 |
|
|
|
|
|
95 |
$this->backup();
|
96 |
|
97 |
-
if ( ! file_exists( $this->get_archive_filepath() ) )
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
return true;
|
101 |
|
@@ -110,11 +94,18 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
110 |
|
111 |
global $is_apache;
|
112 |
|
113 |
-
|
114 |
-
|
115 |
|
116 |
-
$
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
|
119 |
if ( file_exists( $backup ) ) {
|
120 |
|
@@ -131,7 +122,10 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
131 |
|
132 |
}
|
133 |
|
134 |
-
|
|
|
|
|
|
|
135 |
|
136 |
}
|
137 |
|
@@ -153,6 +147,17 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
153 |
|
154 |
}
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
/**
|
157 |
* Get the estimated size of the sites files and database
|
158 |
*
|
@@ -179,7 +184,8 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
179 |
|
180 |
// we dont know the size yet, fire off a remote request to get it for later
|
181 |
// it can take some time so we have a small timeout then return "Calculating"
|
182 |
-
|
|
|
183 |
|
184 |
return __( 'Calculating', 'wpremote' );
|
185 |
|
@@ -192,8 +198,16 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
192 |
*/
|
193 |
protected function do_action( $action ) {
|
194 |
|
|
|
|
|
195 |
switch ( $action ) :
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
case 'hmbkp_mysqldump_started' :
|
198 |
|
199 |
$this->set_status( sprintf( __( 'Dumping Database %s', 'wpremote' ), '(<code>' . $this->get_mysqldump_method() . '</code>)' ) );
|
@@ -208,7 +222,12 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
208 |
|
209 |
case 'hmbkp_archive_started' :
|
210 |
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
212 |
|
213 |
break;
|
214 |
|
@@ -223,6 +242,8 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
223 |
if ( file_exists( $this->get_schedule_running_path() ) )
|
224 |
unlink( $this->get_schedule_running_path() );
|
225 |
|
|
|
|
|
226 |
break;
|
227 |
|
228 |
case 'hmbkp_error' :
|
@@ -414,6 +435,161 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
414 |
|
415 |
}
|
416 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
/**
|
418 |
* Calculate the size of the backup
|
419 |
*
|
@@ -475,7 +651,7 @@ class WPRP_Backups extends WPRP_HM_Backup {
|
|
475 |
|
476 |
}
|
477 |
|
478 |
-
|
479 |
* Return an array of back meta information
|
480 |
*
|
481 |
* @return array
|
@@ -499,6 +675,9 @@ function _wprp_get_backups_info() {
|
|
499 |
*/
|
500 |
function wprp_ajax_calculate_backup_size() {
|
501 |
|
|
|
|
|
|
|
502 |
WPRP_Backups::get_instance()->get_filesize();
|
503 |
|
504 |
exit;
|
23 |
*/
|
24 |
public static function get_instance() {
|
25 |
|
26 |
+
if ( empty( self::$instance ) ) {
|
27 |
self::$instance = new WPRP_Backups();
|
28 |
+
self::$instance->set_is_using_file_manifest( apply_filters( 'wprp_backups_use_file_manifest', false ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
}
|
31 |
|
32 |
+
return self::$instance;
|
33 |
|
34 |
}
|
35 |
|
46 |
|
47 |
// Set the excludes
|
48 |
if ( class_exists( 'WPR_API_Request' ) && WPR_API_Request::get_arg( 'backup_excludes' ) )
|
49 |
+
$backup_excludes = WPR_API_Request::get_arg( 'backup_excludes' );
|
50 |
else if ( isset( $_GET['backup_excludes'] ) )
|
51 |
+
$backup_excludes = $_GET['backup_excludes'];
|
52 |
+
|
53 |
+
if ( ! empty( $backup_excludes ) )
|
54 |
+
$this->set_excludes( apply_filters( 'wprp_backup_excludes', $backup_excludes ) );
|
55 |
|
56 |
$this->filesize_transient = 'wprp_' . '_' . $this->get_type() . '_' . substr( md5( $this->exclude_string() ), 20 ) . '_filesize';
|
57 |
|
67 |
|
68 |
$this->set_status( 'Starting backup...' );
|
69 |
|
70 |
+
$this->set_start_timestamp();
|
71 |
+
|
72 |
$this->backup();
|
73 |
|
74 |
+
if ( ! file_exists( $this->get_archive_filepath() ) ) {
|
75 |
+
|
76 |
+
$errors = $this->get_errors();
|
77 |
+
if ( ! empty( $errors ) )
|
78 |
+
return new WP_Error( 'backup-failed', implode( ', ', $errors ) );
|
79 |
+
else
|
80 |
+
return new WP_Error( 'backup-failed', __( 'Backup file is missing.', 'wpremote' ) );
|
81 |
+
|
82 |
+
}
|
83 |
|
84 |
return true;
|
85 |
|
94 |
|
95 |
global $is_apache;
|
96 |
|
97 |
+
// Restore the start timestamp to global scope so HM Backup recognizes the proper archive file
|
98 |
+
$this->restore_start_timestamp();
|
99 |
|
100 |
+
if ( $status = $this->get_status() ) {
|
101 |
+
|
102 |
+
if ( $this->is_backup_still_running() )
|
103 |
+
return new WP_Error( 'error-status', $status );
|
104 |
+
else
|
105 |
+
return new WP_Error( 'backup-process-killed', __( 'Backup process failed or was killed.', 'wpremote' ) );
|
106 |
+
}
|
107 |
+
|
108 |
+
$backup = $this->get_archive_filepath();
|
109 |
|
110 |
if ( file_exists( $backup ) ) {
|
111 |
|
122 |
|
123 |
}
|
124 |
|
125 |
+
$response = new stdClass;
|
126 |
+
$response->url = str_replace( parent::conform_dir( WP_CONTENT_DIR ), WP_CONTENT_URL, $backup );
|
127 |
+
$response->seconds_elapsed = time() - $this->start_timestamp;
|
128 |
+
return $response;
|
129 |
|
130 |
}
|
131 |
|
147 |
|
148 |
}
|
149 |
|
150 |
+
/**
|
151 |
+
* Cleanup old ZipArchive partials that may have been left by old processes
|
152 |
+
*/
|
153 |
+
public function cleanup_ziparchive_partials() {
|
154 |
+
|
155 |
+
foreach( glob( $this->get_path() . '/*.zip.*' ) as $ziparchive_partial ) {
|
156 |
+
unlink( $ziparchive_partial );
|
157 |
+
}
|
158 |
+
|
159 |
+
}
|
160 |
+
|
161 |
/**
|
162 |
* Get the estimated size of the sites files and database
|
163 |
*
|
184 |
|
185 |
// we dont know the size yet, fire off a remote request to get it for later
|
186 |
// it can take some time so we have a small timeout then return "Calculating"
|
187 |
+
global $wprp_noauth_nonce;
|
188 |
+
wp_remote_get( add_query_arg( array( 'action' => 'wprp_calculate_backup_size', 'backup_excludes' => $this->get_excludes() ), add_query_arg( '_wpnonce', $wprp_noauth_nonce, admin_url( 'admin-ajax.php' ) ) ), array( 'timeout' => 0.1, 'sslverify' => false ) );
|
189 |
|
190 |
return __( 'Calculating', 'wpremote' );
|
191 |
|
198 |
*/
|
199 |
protected function do_action( $action ) {
|
200 |
|
201 |
+
$this->update_heartbeat_timestamp();
|
202 |
+
|
203 |
switch ( $action ) :
|
204 |
|
205 |
+
case 'hmbkp_backup_started':
|
206 |
+
|
207 |
+
$this->save_backup_process_id();
|
208 |
+
|
209 |
+
break;
|
210 |
+
|
211 |
case 'hmbkp_mysqldump_started' :
|
212 |
|
213 |
$this->set_status( sprintf( __( 'Dumping Database %s', 'wpremote' ), '(<code>' . $this->get_mysqldump_method() . '</code>)' ) );
|
222 |
|
223 |
case 'hmbkp_archive_started' :
|
224 |
|
225 |
+
if ( $this->is_using_file_manifest() )
|
226 |
+
$status = sprintf( __( '%d files remaining to archive %s', 'wpremote' ), $this->file_manifest_remaining, '(<code>' . $this->get_archive_method() . '</code>)' );
|
227 |
+
else
|
228 |
+
$status = sprintf( __( 'Creating zip archive %s', 'wpremote' ), '(<code>' . $this->get_archive_method() . '</code>)' );
|
229 |
+
|
230 |
+
$this->set_status( $status );
|
231 |
|
232 |
break;
|
233 |
|
242 |
if ( file_exists( $this->get_schedule_running_path() ) )
|
243 |
unlink( $this->get_schedule_running_path() );
|
244 |
|
245 |
+
$this->clear_backup_process_id();
|
246 |
+
|
247 |
break;
|
248 |
|
249 |
case 'hmbkp_error' :
|
435 |
|
436 |
}
|
437 |
|
438 |
+
/**
|
439 |
+
* Set the start timestamp for the backup
|
440 |
+
*/
|
441 |
+
private function set_start_timestamp() {
|
442 |
+
$this->start_timestamp = current_time( 'timestamp' );
|
443 |
+
file_put_contents( $this->get_path() . '/.start-timestamp', $this->start_timestamp );
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* Restore the start timestamp for the backup
|
448 |
+
*/
|
449 |
+
private function restore_start_timestamp() {
|
450 |
+
if ( $start_timestamp = file_get_contents( $this->get_path() . '/.start-timestamp' ) )
|
451 |
+
$this->start_timestamp = (int) $start_timestamp;
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* Update the heartbeat timestamp to the current time.
|
456 |
+
*/
|
457 |
+
private function update_heartbeat_timestamp() {
|
458 |
+
file_put_contents( $this->get_path() . '/.heartbeat-timestamp', time() );
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* Get the heartbeat timestamp.
|
463 |
+
*/
|
464 |
+
private function get_heartbeat_timestamp() {
|
465 |
+
|
466 |
+
$heartbeat = $this->get_path() . '/.heartbeat-timestamp';
|
467 |
+
|
468 |
+
if ( file_exists( $heartbeat ) )
|
469 |
+
return (int) file_get_contents( $heartbeat );
|
470 |
+
|
471 |
+
return false;
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Get the file path to the backup process ID log
|
476 |
+
*
|
477 |
+
* @access private
|
478 |
+
*/
|
479 |
+
private function get_backup_process_id_path() {
|
480 |
+
return $this->get_path() . '/.backup-process-id';
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Get the current backup process ID
|
485 |
+
*
|
486 |
+
* @access private
|
487 |
+
*/
|
488 |
+
private function get_backup_process_id() {
|
489 |
+
$file = $this->get_backup_process_id_path();
|
490 |
+
if ( file_exists( $file ) )
|
491 |
+
return (int) trim( file_get_contents( $file ) );
|
492 |
+
else
|
493 |
+
return false;
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* Save this current backup process ID in case
|
498 |
+
* we need to check later whether it was killed in action
|
499 |
+
*
|
500 |
+
* @access private
|
501 |
+
*/
|
502 |
+
private function save_backup_process_id() {
|
503 |
+
|
504 |
+
if ( ! $handle = fopen( $this->get_backup_process_id_path(), 'w' ) )
|
505 |
+
return;
|
506 |
+
|
507 |
+
fwrite( $handle, getmypid() );
|
508 |
+
|
509 |
+
fclose( $handle );
|
510 |
+
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Clear the backup process ID
|
515 |
+
*
|
516 |
+
* @access private
|
517 |
+
*/
|
518 |
+
private function clear_backup_process_id() {
|
519 |
+
|
520 |
+
if ( file_exists( $this->get_backup_process_id_path() ) )
|
521 |
+
unlink( $this->get_backup_process_id_path() );
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* Whether or not a backup appears to be in progress
|
526 |
+
*
|
527 |
+
* @access private
|
528 |
+
*/
|
529 |
+
private function is_backup_still_running() {
|
530 |
+
|
531 |
+
// Check whether there's supposed to be a backup in progress
|
532 |
+
if ( false == ( $process_id = $this->get_backup_process_id() ) )
|
533 |
+
return false;
|
534 |
+
|
535 |
+
$time_to_wait = 120;
|
536 |
+
|
537 |
+
// If the heartbeat has been modified in the last 90 seconds, we might not be dead
|
538 |
+
if ( ( time() - $this->get_heartbeat_timestamp() ) < $time_to_wait )
|
539 |
+
return true;
|
540 |
+
|
541 |
+
// Check if the database archive was modified recently
|
542 |
+
$database = $this->get_database_dump_filepath();
|
543 |
+
if ( file_exists( $database ) && ( ( time() - filemtime( $database ) ) < $time_to_wait ) )
|
544 |
+
return true;
|
545 |
+
|
546 |
+
// Check if there's a ZipArchive file being modified.
|
547 |
+
$ziparchive_files = glob( $this->get_path() . '/*.zip.*' );
|
548 |
+
$ziparchive_mtimes = array();
|
549 |
+
foreach( $ziparchive_files as $ziparchive_file ) {
|
550 |
+
$ziparchive_mtimes[] = filemtime( $ziparchive_file );
|
551 |
+
}
|
552 |
+
if ( ! empty( $ziparchive_mtimes ) ) {
|
553 |
+
$latest_ziparchive_mtime = max( $ziparchive_mtimes );
|
554 |
+
if ( ( time() - $latest_ziparchive_mtime ) < $time_to_wait )
|
555 |
+
return true;
|
556 |
+
}
|
557 |
+
|
558 |
+
return false;
|
559 |
+
}
|
560 |
+
|
561 |
+
/**
|
562 |
+
* Check if there's a backup in progress, whether it's running,
|
563 |
+
* and restart it if it's not running
|
564 |
+
*
|
565 |
+
* @todo support checking whether the database should exist
|
566 |
+
*/
|
567 |
+
public function backup_heartbeat() {
|
568 |
+
|
569 |
+
// Restore the start timestamp to global scope so HM Backup recognizes the proper archive file
|
570 |
+
$this->restore_start_timestamp();
|
571 |
+
|
572 |
+
// No process means no backup in progress
|
573 |
+
if ( ! $this->get_backup_process_id() )
|
574 |
+
return false;
|
575 |
+
|
576 |
+
// No file manifest directory means this wasn't a file manifest approach
|
577 |
+
if ( ! is_dir( $this->get_file_manifest_dirpath() ) )
|
578 |
+
return false;
|
579 |
+
|
580 |
+
// Check whether there's supposed to be a backup in progress
|
581 |
+
if ( $this->get_backup_process_id() && $this->is_backup_still_running() )
|
582 |
+
return false;
|
583 |
+
|
584 |
+
// Uh oh, needs to be restarted
|
585 |
+
$this->cleanup_ziparchive_partials();
|
586 |
+
|
587 |
+
$this->save_backup_process_id();
|
588 |
+
|
589 |
+
$this->restart_archive();
|
590 |
+
|
591 |
+
}
|
592 |
+
|
593 |
/**
|
594 |
* Calculate the size of the backup
|
595 |
*
|
651 |
|
652 |
}
|
653 |
|
654 |
+
/*
|
655 |
* Return an array of back meta information
|
656 |
*
|
657 |
* @return array
|
675 |
*/
|
676 |
function wprp_ajax_calculate_backup_size() {
|
677 |
|
678 |
+
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'wprp_calculate_backup_size' ) )
|
679 |
+
exit;
|
680 |
+
|
681 |
WPRP_Backups::get_instance()->get_filesize();
|
682 |
|
683 |
exit;
|
wprp.hm.backup.php
CHANGED
@@ -23,6 +23,14 @@ class WPRP_HM_Backup {
|
|
23 |
*/
|
24 |
private $type = '';
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
/**
|
27 |
* The filename of the backup file
|
28 |
*
|
@@ -138,6 +146,54 @@ class WPRP_HM_Backup {
|
|
138 |
*/
|
139 |
private $mysqldump_method = '';
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
/**
|
142 |
* Check whether safe mode is active or not
|
143 |
*
|
@@ -271,8 +327,13 @@ class WPRP_HM_Backup {
|
|
271 |
*/
|
272 |
public function get_archive_filename() {
|
273 |
|
274 |
-
if ( empty( $this->archive_filename ) )
|
275 |
-
|
|
|
|
|
|
|
|
|
|
|
276 |
|
277 |
return $this->archive_filename;
|
278 |
|
@@ -425,6 +486,161 @@ class WPRP_HM_Backup {
|
|
425 |
return $this->mysqldump_method;
|
426 |
}
|
427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
/**
|
429 |
* Get the backup type
|
430 |
*
|
@@ -595,6 +811,60 @@ class WPRP_HM_Backup {
|
|
595 |
|
596 |
}
|
597 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
598 |
protected function do_action( $action ) {
|
599 |
|
600 |
do_action( $action, $this );
|
@@ -767,6 +1037,147 @@ class WPRP_HM_Backup {
|
|
767 |
*/
|
768 |
public function archive() {
|
769 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
770 |
// Do we have the path to the zip command
|
771 |
if ( $this->get_zip_command_path() )
|
772 |
$this->zip();
|
@@ -787,6 +1198,26 @@ class WPRP_HM_Backup {
|
|
787 |
|
788 |
}
|
789 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
790 |
/**
|
791 |
* Zip using the native zip command
|
792 |
*
|
@@ -799,13 +1230,15 @@ class WPRP_HM_Backup {
|
|
799 |
$this->do_action( 'hmbkp_archive_started' );
|
800 |
|
801 |
// Zip up $this->root with excludes
|
802 |
-
if ( $this->get_type() !== 'database' && $this->exclude_string( 'zip' ) )
|
803 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' -x ' . $this->exclude_string( 'zip' ) . ' 2>&1' );
|
804 |
|
805 |
// Zip up $this->root without excludes
|
806 |
-
elseif ( $this->get_type() !== 'database' )
|
807 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' 2>&1' );
|
808 |
|
|
|
|
|
809 |
// Add the database dump to the archive
|
810 |
if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) )
|
811 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_path() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -uq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . escapeshellarg( $this->get_database_dump_filename() ) . ' 2>&1' );
|
@@ -814,7 +1247,25 @@ class WPRP_HM_Backup {
|
|
814 |
$this->warning( $this->get_archive_method(), $stderr );
|
815 |
|
816 |
$this->verify_archive();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
817 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
818 |
}
|
819 |
|
820 |
/**
|
@@ -828,10 +1279,8 @@ class WPRP_HM_Backup {
|
|
828 |
|
829 |
$this->do_action( 'hmbkp_archive_started' );
|
830 |
|
831 |
-
|
832 |
-
|
833 |
-
if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE ) )
|
834 |
-
return;
|
835 |
|
836 |
$excludes = $this->exclude_string( 'regex' );
|
837 |
|
@@ -883,6 +1332,31 @@ class WPRP_HM_Backup {
|
|
883 |
|
884 |
}
|
885 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
886 |
/**
|
887 |
* Fallback for creating zip archives if zip command and ZipArchive are
|
888 |
* unavailable.
|
@@ -900,9 +1374,7 @@ class WPRP_HM_Backup {
|
|
900 |
|
901 |
$_wprp_hmbkp_exclude_string = $this->exclude_string( 'regex' );
|
902 |
|
903 |
-
$this->
|
904 |
-
|
905 |
-
$archive = new PclZip( $this->get_archive_filepath() );
|
906 |
|
907 |
// Zip up everything
|
908 |
if ( $this->get_type() !== 'database' )
|
@@ -920,6 +1392,28 @@ class WPRP_HM_Backup {
|
|
920 |
|
921 |
}
|
922 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
923 |
public function verify_mysqldump() {
|
924 |
|
925 |
$this->do_action( 'hmbkp_mysqldump_verify_started' );
|
@@ -1593,10 +2087,10 @@ class WPRP_HM_Backup {
|
|
1593 |
if ( ! $handle = @fopen( $sqlname, 'a' ) )
|
1594 |
return;
|
1595 |
|
1596 |
-
if ( ! fwrite( $handle, $sql ) )
|
1597 |
return;
|
1598 |
|
1599 |
-
fclose( $handle );
|
1600 |
|
1601 |
return true;
|
1602 |
|
@@ -1630,10 +2124,10 @@ class WPRP_HM_Backup {
|
|
1630 |
if ( empty( $context ) || empty( $error ) )
|
1631 |
return;
|
1632 |
|
1633 |
-
$this->do_action( 'hmbkp_error' );
|
1634 |
-
|
1635 |
$this->errors[$context][$_key = md5( implode( ':' , (array) $error ) )] = $error;
|
1636 |
|
|
|
|
|
1637 |
}
|
1638 |
|
1639 |
/**
|
@@ -1715,6 +2209,37 @@ class WPRP_HM_Backup {
|
|
1715 |
|
1716 |
}
|
1717 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1718 |
}
|
1719 |
|
1720 |
/**
|
23 |
*/
|
24 |
private $type = '';
|
25 |
|
26 |
+
/**
|
27 |
+
* The start timestamp of the backup
|
28 |
+
*
|
29 |
+
* @int
|
30 |
+
* @access protected
|
31 |
+
*/
|
32 |
+
protected $start_timestamp;
|
33 |
+
|
34 |
/**
|
35 |
* The filename of the backup file
|
36 |
*
|
146 |
*/
|
147 |
private $mysqldump_method = '';
|
148 |
|
149 |
+
/**
|
150 |
+
* Whether or not to use a file manifest (more write-intensive)
|
151 |
+
*
|
152 |
+
* @var bool
|
153 |
+
* @access private
|
154 |
+
*/
|
155 |
+
private $using_file_manifest = false;
|
156 |
+
|
157 |
+
/**
|
158 |
+
* The current file manifest file.
|
159 |
+
*
|
160 |
+
* @access private
|
161 |
+
*/
|
162 |
+
private $current_file_manifest = false;
|
163 |
+
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Files of the file manifest that have already been archived
|
167 |
+
*
|
168 |
+
* @access private
|
169 |
+
*/
|
170 |
+
private $file_manifest_already_archived = array();
|
171 |
+
|
172 |
+
/**
|
173 |
+
* When using the file manifest, the number of files that should be
|
174 |
+
* archived per batch.
|
175 |
+
*
|
176 |
+
* @access private
|
177 |
+
*/
|
178 |
+
private $file_manifest_per_batch = 200;
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Files remaining to be achived in the file manifest.
|
182 |
+
*
|
183 |
+
* @access protected
|
184 |
+
*/
|
185 |
+
protected $file_manifest_remaining = 0;
|
186 |
+
|
187 |
+
/**
|
188 |
+
* A ZipArchive instance for this instance
|
189 |
+
*/
|
190 |
+
private $ziparchive = false;
|
191 |
+
|
192 |
+
/**
|
193 |
+
* A PclZip instance for this instance
|
194 |
+
*/
|
195 |
+
private $pclzip = false;
|
196 |
+
|
197 |
/**
|
198 |
* Check whether safe mode is active or not
|
199 |
*
|
327 |
*/
|
328 |
public function get_archive_filename() {
|
329 |
|
330 |
+
if ( empty( $this->archive_filename ) ) {
|
331 |
+
|
332 |
+
if ( empty( $this->start_timestamp ) )
|
333 |
+
$this->start_timestamp = current_time( 'timestamp' );
|
334 |
+
|
335 |
+
$this->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), 'backup', date( 'Y-m-d-H-i-s', $this->start_timestamp ) ) ) . '.zip' );
|
336 |
+
}
|
337 |
|
338 |
return $this->archive_filename;
|
339 |
|
486 |
return $this->mysqldump_method;
|
487 |
}
|
488 |
|
489 |
+
/**
|
490 |
+
* Whether or not to use the file manifest
|
491 |
+
*
|
492 |
+
* @access public
|
493 |
+
*/
|
494 |
+
public function is_using_file_manifest() {
|
495 |
+
return (bool)$this->using_file_manifest;
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Set whether or not to use the file manifest
|
500 |
+
*
|
501 |
+
* @access public
|
502 |
+
*/
|
503 |
+
public function set_is_using_file_manifest( $val ) {
|
504 |
+
$this->using_file_manifest = (bool)$val;
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Create a series of file manifests for the backup
|
509 |
+
*
|
510 |
+
* @access private
|
511 |
+
*/
|
512 |
+
private function create_file_manifests() {
|
513 |
+
|
514 |
+
if ( is_dir( $this->get_file_manifest_dirpath() ) )
|
515 |
+
$this->rmdir_recursive( $this->get_file_manifest_dirpath() );
|
516 |
+
|
517 |
+
mkdir( $this->get_file_manifest_dirpath(), 0755 );
|
518 |
+
|
519 |
+
// Protect against directory browsing by including a index.html file
|
520 |
+
$index = $this->get_file_manifest_dirpath() . '/index.html';
|
521 |
+
if ( ! file_exists( $index ) && is_writable( $this->get_file_manifest_dirpath() ) )
|
522 |
+
file_put_contents( $index, '' );
|
523 |
+
|
524 |
+
$excludes = $this->exclude_string( 'regex' );
|
525 |
+
|
526 |
+
$file_manifest = array();
|
527 |
+
$this->file_manifest_remaining = 0;
|
528 |
+
$file_manifest_file_count = 0;
|
529 |
+
$current_batch = 0;
|
530 |
+
foreach( $this->get_files() as $file ) {
|
531 |
+
|
532 |
+
// Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
|
533 |
+
if ( method_exists( $file, 'isDot' ) && $file->isDot() )
|
534 |
+
continue;
|
535 |
+
|
536 |
+
// Skip unreadable files
|
537 |
+
if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() )
|
538 |
+
continue;
|
539 |
+
|
540 |
+
// Excludes
|
541 |
+
if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) )
|
542 |
+
continue;
|
543 |
+
|
544 |
+
if ( $file->isDir() )
|
545 |
+
$line = trailingslashit( str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) );
|
546 |
+
|
547 |
+
elseif ( $file->isFile() )
|
548 |
+
$line = str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) );
|
549 |
+
|
550 |
+
// File manifest is full
|
551 |
+
if ( ! empty( $current_file ) && $current_batch >= $this->file_manifest_per_batch ) {
|
552 |
+
|
553 |
+
@fclose( $current_file );
|
554 |
+
$current_file = false;
|
555 |
+
|
556 |
+
}
|
557 |
+
|
558 |
+
// Create a new file manifest
|
559 |
+
if ( empty( $current_file ) ) {
|
560 |
+
|
561 |
+
$file_manifest_file_count++;
|
562 |
+
$file_manifest_filename = str_pad( $file_manifest_file_count, 10, "0", STR_PAD_LEFT );
|
563 |
+
if ( ! $current_file = @fopen( $this->get_file_manifest_dirpath() . '/' . $file_manifest_filename . '.txt', 'w' ) )
|
564 |
+
return false;
|
565 |
+
|
566 |
+
$current_batch = 0;
|
567 |
+
}
|
568 |
+
|
569 |
+
// Write the line to the file manifest if it isn't empty for some reason
|
570 |
+
if ( ! empty( $line ) ) {
|
571 |
+
@fwrite( $current_file, $line . PHP_EOL );
|
572 |
+
unset( $line );
|
573 |
+
$this->file_manifest_remaining++;
|
574 |
+
$current_batch++;
|
575 |
+
}
|
576 |
+
|
577 |
+
}
|
578 |
+
|
579 |
+
@file_put_contents( $this->get_path() . '/.file-manifest-remaining', $this->file_manifest_remaining );
|
580 |
+
|
581 |
+
return true;
|
582 |
+
}
|
583 |
+
|
584 |
+
/**
|
585 |
+
* Delete the current file manifest
|
586 |
+
*
|
587 |
+
* @access private
|
588 |
+
*/
|
589 |
+
private function delete_current_file_manifest() {
|
590 |
+
|
591 |
+
if ( ! file_exists( $this->current_file_manifest ) )
|
592 |
+
return false;
|
593 |
+
|
594 |
+
// Remove the file manifest because it's already been archived
|
595 |
+
unlink( $this->current_file_manifest );
|
596 |
+
|
597 |
+
// Update the count of remaining files.
|
598 |
+
$this->file_manifest_remaining = $this->file_manifest_remaining - count( $this->file_manifest_already_archived );
|
599 |
+
if ( $this->file_manifest_remaining < 0 )
|
600 |
+
$this->file_manifest_remaining = 0;
|
601 |
+
file_put_contents( $this->get_path() . '/.file-manifest-remaining', $this->file_manifest_remaining );
|
602 |
+
|
603 |
+
$this->file_manifest_already_archived = array();
|
604 |
+
|
605 |
+
}
|
606 |
+
|
607 |
+
|
608 |
+
/**
|
609 |
+
* Get the path to the file manifest directory
|
610 |
+
*
|
611 |
+
* @access private
|
612 |
+
*/
|
613 |
+
protected function get_file_manifest_dirpath() {
|
614 |
+
return $this->get_path() . '/.file-manifests';
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get batch of files to archive from the file manifest
|
619 |
+
* Ignore any files that already have been archived
|
620 |
+
*
|
621 |
+
* @access private
|
622 |
+
*/
|
623 |
+
private function get_next_files_from_file_manifest() {
|
624 |
+
|
625 |
+
if ( ! is_dir( $this->get_file_manifest_dirpath() ) )
|
626 |
+
return array();
|
627 |
+
|
628 |
+
$files = glob( $this->get_file_manifest_dirpath() . '/*.txt' );
|
629 |
+
if ( empty( $files ) )
|
630 |
+
return array();
|
631 |
+
|
632 |
+
$this->current_file_manifest = array_shift( $files );
|
633 |
+
|
634 |
+
$files = file_get_contents( $this->current_file_manifest );
|
635 |
+
$files = array_map( 'trim', explode( PHP_EOL, $files ) );
|
636 |
+
if ( empty( $files ) )
|
637 |
+
return array();
|
638 |
+
|
639 |
+
$this->file_manifest_remaining = (int)file_get_contents( $this->get_path() . '/.file-manifest-remaining' );
|
640 |
+
|
641 |
+
return $files;
|
642 |
+
}
|
643 |
+
|
644 |
/**
|
645 |
* Get the backup type
|
646 |
*
|
811 |
|
812 |
}
|
813 |
|
814 |
+
/**
|
815 |
+
* Set up the ZipArchive instance if ZipArchive is available
|
816 |
+
*/
|
817 |
+
protected function &setup_ziparchive() {
|
818 |
+
|
819 |
+
// Instance is already open
|
820 |
+
if ( ! empty( $this->ziparchive ) ) {
|
821 |
+
$this->ziparchive->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE );
|
822 |
+
return $this->ziparchive;
|
823 |
+
}
|
824 |
+
|
825 |
+
$ziparchive = new ZipArchive;
|
826 |
+
|
827 |
+
// Try opening ZipArchive
|
828 |
+
if ( ! file_exists( $this->get_archive_filepath() ) )
|
829 |
+
$ret = $ziparchive->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE );
|
830 |
+
else
|
831 |
+
$ret = $ziparchive->open( $this->get_archive_filepath() );
|
832 |
+
|
833 |
+
// File couldn't be opened
|
834 |
+
if ( ! $ret )
|
835 |
+
return false;
|
836 |
+
|
837 |
+
// Try closing ZipArchive
|
838 |
+
$ret = $ziparchive->close();
|
839 |
+
|
840 |
+
// File couldn't be closed
|
841 |
+
if ( ! $ret )
|
842 |
+
return false;
|
843 |
+
|
844 |
+
// Open it once more
|
845 |
+
if ( ! file_exists( $this->get_archive_filepath() ) )
|
846 |
+
$ziparchive->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE );
|
847 |
+
else
|
848 |
+
$ziparchive->open( $this->get_archive_filepath() );
|
849 |
+
|
850 |
+
$this->ziparchive = $ziparchive;
|
851 |
+
return $this->ziparchive;
|
852 |
+
}
|
853 |
+
|
854 |
+
/**
|
855 |
+
* Set up the PclZip instance
|
856 |
+
*
|
857 |
+
* @access protected
|
858 |
+
*/
|
859 |
+
protected function &setup_pclzip() {
|
860 |
+
|
861 |
+
if ( empty( $this->pclzip ) ) {
|
862 |
+
$this->load_pclzip();
|
863 |
+
$this->pclzip = new PclZip( $this->get_archive_filepath() );
|
864 |
+
}
|
865 |
+
return $this->pclzip;
|
866 |
+
}
|
867 |
+
|
868 |
protected function do_action( $action ) {
|
869 |
|
870 |
do_action( $action, $this );
|
1037 |
*/
|
1038 |
public function archive() {
|
1039 |
|
1040 |
+
// If using a manifest, perform the backup in chunks
|
1041 |
+
if ( 'database' !== $this->get_type()
|
1042 |
+
&& $this->is_using_file_manifest()
|
1043 |
+
&& $this->create_file_manifests() ) {
|
1044 |
+
|
1045 |
+
$this->archive_via_file_manifest();
|
1046 |
+
|
1047 |
+
} else {
|
1048 |
+
|
1049 |
+
$this->archive_via_single_request();
|
1050 |
+
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
/**
|
1056 |
+
* Archive with a file manifest
|
1057 |
+
*
|
1058 |
+
* @access private
|
1059 |
+
*/
|
1060 |
+
private function archive_via_file_manifest() {
|
1061 |
+
|
1062 |
+
$errors = array();
|
1063 |
+
|
1064 |
+
// Back up files from the file manifest in chunks
|
1065 |
+
$next_files = $this->get_next_files_from_file_manifest();
|
1066 |
+
do {
|
1067 |
+
|
1068 |
+
$this->do_action( 'hmbkp_archive_started' );
|
1069 |
+
|
1070 |
+
// ZipArchive is the fastest for chunked backups
|
1071 |
+
if ( class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) ) {
|
1072 |
+
$this->archive_method = 'zip_archive_files';
|
1073 |
+
|
1074 |
+
$ret = $this->zip_archive_files( $next_files );
|
1075 |
+
if ( ! $ret ) {
|
1076 |
+
$this->skip_zip_archive = true;
|
1077 |
+
continue;
|
1078 |
+
}
|
1079 |
+
}
|
1080 |
+
|
1081 |
+
// Fall back to `zip` if ZipArchive doesn't exist
|
1082 |
+
else if ( $this->get_zip_command_path() ) {
|
1083 |
+
$this->archive_method = 'zip_files';
|
1084 |
+
$error = $this->zip_files( $next_files );
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
// Last opportunity
|
1088 |
+
else {
|
1089 |
+
$this->archive_method = 'pcl_zip_files';
|
1090 |
+
$error = $this->pcl_zip_files( $next_files );
|
1091 |
+
}
|
1092 |
+
|
1093 |
+
if ( ! empty( $error ) ) {
|
1094 |
+
$errors[] = $error;
|
1095 |
+
unset( $error );
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
// Update the file manifest with these files that were archived
|
1099 |
+
$this->file_manifest_already_archived = array_merge( $this->file_manifest_already_archived, $next_files );
|
1100 |
+
$this->delete_current_file_manifest();
|
1101 |
+
|
1102 |
+
// Get the next set of files to archive
|
1103 |
+
$next_files = $this->get_next_files_from_file_manifest();
|
1104 |
+
|
1105 |
+
} while( ! empty( $next_files ) );
|
1106 |
+
|
1107 |
+
// If the database should be included in the backup, it's included last
|
1108 |
+
if ( 'file' !== $this->get_type() && file_exists( $this->get_database_dump_filepath() ) ) {
|
1109 |
+
|
1110 |
+
switch ( $this->archive_method ) {
|
1111 |
+
|
1112 |
+
case 'zip_archive_files':
|
1113 |
+
|
1114 |
+
$zip = &$this->setup_ziparchive();
|
1115 |
+
|
1116 |
+
$zip->addFile( $this->get_database_dump_filepath(), $this->get_database_dump_filename() );
|
1117 |
+
|
1118 |
+
$zip->close();
|
1119 |
+
|
1120 |
+
break;
|
1121 |
+
|
1122 |
+
case 'zip_files':
|
1123 |
+
|
1124 |
+
$error = shell_exec( 'cd ' . escapeshellarg( $this->get_path() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -uq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . escapeshellarg( $this->get_database_dump_filename() ) . ' 2>&1' );
|
1125 |
+
|
1126 |
+
break;
|
1127 |
+
|
1128 |
+
case 'pcl_zip_files':
|
1129 |
+
|
1130 |
+
$pclzip = &$this->setup_pclzip();
|
1131 |
+
|
1132 |
+
if ( ! $pclzip->add( $this->get_database_dump_filepath(), PCLZIP_OPT_REMOVE_PATH, $this->get_path() ) )
|
1133 |
+
$this->warning( $this->get_archive_method(), $pclzip->errorInfo( true ) );
|
1134 |
+
|
1135 |
+
break;
|
1136 |
+
}
|
1137 |
+
|
1138 |
+
if ( ! empty( $error ) ) {
|
1139 |
+
$errors[] = $error;
|
1140 |
+
unset( $error );
|
1141 |
+
}
|
1142 |
+
}
|
1143 |
+
|
1144 |
+
// If the methods produced any errors, log them
|
1145 |
+
if ( ! empty( $errors ) )
|
1146 |
+
$this->warning( $this->get_archive_method(), implode( ', ', $errors ) );
|
1147 |
+
|
1148 |
+
// ZipArchive has some special reporting requirements
|
1149 |
+
if ( ! empty( $this->ziparchive ) ) {
|
1150 |
+
|
1151 |
+
if ( $this->ziparchive->status )
|
1152 |
+
$this->warning( $this->get_archive_method(), $this->ziparchive->status );
|
1153 |
+
|
1154 |
+
if ( $this->ziparchive->statusSys )
|
1155 |
+
$this->warning( $this->get_archive_method(), $this->ziparchive->statusSys );
|
1156 |
+
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
// Verify and remove if errors
|
1160 |
+
$this->verify_archive();
|
1161 |
+
|
1162 |
+
// Remove the file manifest
|
1163 |
+
if ( is_dir( $this->get_file_manifest_dirpath() ) )
|
1164 |
+
$this->rmdir_recursive( $this->get_file_manifest_dirpath() );
|
1165 |
+
|
1166 |
+
// Delete the database dump file
|
1167 |
+
if ( file_exists( $this->get_database_dump_filepath() ) )
|
1168 |
+
unlink( $this->get_database_dump_filepath() );
|
1169 |
+
|
1170 |
+
$this->do_action( 'hmbkp_archive_finished' );
|
1171 |
+
|
1172 |
+
}
|
1173 |
+
|
1174 |
+
/**
|
1175 |
+
* Archive using our traditional method of one request
|
1176 |
+
*
|
1177 |
+
* @access private
|
1178 |
+
*/
|
1179 |
+
private function archive_via_single_request() {
|
1180 |
+
|
1181 |
// Do we have the path to the zip command
|
1182 |
if ( $this->get_zip_command_path() )
|
1183 |
$this->zip();
|
1198 |
|
1199 |
}
|
1200 |
|
1201 |
+
/**
|
1202 |
+
* Restart a failed archive process
|
1203 |
+
*
|
1204 |
+
* @access public
|
1205 |
+
*/
|
1206 |
+
public function restart_archive() {
|
1207 |
+
|
1208 |
+
if ( $this->is_using_file_manifest() ) {
|
1209 |
+
|
1210 |
+
$this->archive_via_file_manifest();
|
1211 |
+
|
1212 |
+
} else {
|
1213 |
+
|
1214 |
+
$this->archive_via_single_request();
|
1215 |
+
|
1216 |
+
}
|
1217 |
+
|
1218 |
+
$this->do_action( 'hmbkp_backup_complete' );
|
1219 |
+
}
|
1220 |
+
|
1221 |
/**
|
1222 |
* Zip using the native zip command
|
1223 |
*
|
1230 |
$this->do_action( 'hmbkp_archive_started' );
|
1231 |
|
1232 |
// Zip up $this->root with excludes
|
1233 |
+
if ( $this->get_type() !== 'database' && $this->exclude_string( 'zip' ) ) {
|
1234 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' -x ' . $this->exclude_string( 'zip' ) . ' 2>&1' );
|
1235 |
|
1236 |
// Zip up $this->root without excludes
|
1237 |
+
} elseif ( $this->get_type() !== 'database' ) {
|
1238 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' 2>&1' );
|
1239 |
|
1240 |
+
}
|
1241 |
+
|
1242 |
// Add the database dump to the archive
|
1243 |
if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) )
|
1244 |
$stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_path() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -uq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . escapeshellarg( $this->get_database_dump_filename() ) . ' 2>&1' );
|
1247 |
$this->warning( $this->get_archive_method(), $stderr );
|
1248 |
|
1249 |
$this->verify_archive();
|
1250 |
+
}
|
1251 |
+
|
1252 |
+
/**
|
1253 |
+
* Zip one or more files
|
1254 |
+
*
|
1255 |
+
* @access private
|
1256 |
+
*/
|
1257 |
+
private function zip_files( $files ) {
|
1258 |
|
1259 |
+
// Not necessary to include directories when using `zip`
|
1260 |
+
foreach( $files as $key => $file ) {
|
1261 |
+
|
1262 |
+
if ( ! is_dir( $file ) )
|
1263 |
+
continue;
|
1264 |
+
|
1265 |
+
unset( $files[$key] );
|
1266 |
+
}
|
1267 |
+
|
1268 |
+
return shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . implode( ' ', $files ) . ' -q 2>&1' );
|
1269 |
}
|
1270 |
|
1271 |
/**
|
1279 |
|
1280 |
$this->do_action( 'hmbkp_archive_started' );
|
1281 |
|
1282 |
+
if ( false === ( $zip = &$this->setup_ziparchive() ) )
|
1283 |
+
return;
|
|
|
|
|
1284 |
|
1285 |
$excludes = $this->exclude_string( 'regex' );
|
1286 |
|
1332 |
|
1333 |
}
|
1334 |
|
1335 |
+
/**
|
1336 |
+
* Zip Archive one or more files
|
1337 |
+
*
|
1338 |
+
* @access private
|
1339 |
+
*/
|
1340 |
+
private function zip_archive_files( $files ) {
|
1341 |
+
|
1342 |
+
if ( false === ( $zip = &$this->setup_ziparchive() ) )
|
1343 |
+
return false;
|
1344 |
+
|
1345 |
+
foreach( $files as $file ) {
|
1346 |
+
|
1347 |
+
$full_path = trailingslashit( $this->get_root() ) . $file;
|
1348 |
+
if ( is_dir( $full_path ) )
|
1349 |
+
$zip->addEmptyDir( $file );
|
1350 |
+
else
|
1351 |
+
$zip->addFile( $full_path, $file );
|
1352 |
+
|
1353 |
+
}
|
1354 |
+
|
1355 |
+
// Avoid limitations in ZipArchive by making sure we save each batch to disk
|
1356 |
+
$zip->close();
|
1357 |
+
return true;
|
1358 |
+
}
|
1359 |
+
|
1360 |
/**
|
1361 |
* Fallback for creating zip archives if zip command and ZipArchive are
|
1362 |
* unavailable.
|
1374 |
|
1375 |
$_wprp_hmbkp_exclude_string = $this->exclude_string( 'regex' );
|
1376 |
|
1377 |
+
$archive = &$this->setup_pclzip();
|
|
|
|
|
1378 |
|
1379 |
// Zip up everything
|
1380 |
if ( $this->get_type() !== 'database' )
|
1392 |
|
1393 |
}
|
1394 |
|
1395 |
+
/**
|
1396 |
+
* Use PclZip to archive batches of files
|
1397 |
+
*/
|
1398 |
+
private function pcl_zip_files( $files ) {
|
1399 |
+
|
1400 |
+
$this->errors_to_warnings( $this->get_archive_method() );
|
1401 |
+
|
1402 |
+
$pclzip = &$this->setup_pclzip();
|
1403 |
+
|
1404 |
+
foreach( $files as $file ) {
|
1405 |
+
|
1406 |
+
$full_path = trailingslashit( $this->get_root() ) . $file;
|
1407 |
+
if ( is_dir( $full_path ) )
|
1408 |
+
continue;
|
1409 |
+
|
1410 |
+
if ( ! $pclzip->add( $full_path, PCLZIP_OPT_REMOVE_PATH, $this->get_root() ) )
|
1411 |
+
$this->warning( $this->get_archive_method(), $pclzip->errorInfo( true ) );
|
1412 |
+
|
1413 |
+
}
|
1414 |
+
|
1415 |
+
}
|
1416 |
+
|
1417 |
public function verify_mysqldump() {
|
1418 |
|
1419 |
$this->do_action( 'hmbkp_mysqldump_verify_started' );
|
2087 |
if ( ! $handle = @fopen( $sqlname, 'a' ) )
|
2088 |
return;
|
2089 |
|
2090 |
+
if ( ! @fwrite( $handle, $sql ) )
|
2091 |
return;
|
2092 |
|
2093 |
+
@fclose( $handle );
|
2094 |
|
2095 |
return true;
|
2096 |
|
2124 |
if ( empty( $context ) || empty( $error ) )
|
2125 |
return;
|
2126 |
|
|
|
|
|
2127 |
$this->errors[$context][$_key = md5( implode( ':' , (array) $error ) )] = $error;
|
2128 |
|
2129 |
+
$this->do_action( 'hmbkp_error' );
|
2130 |
+
|
2131 |
}
|
2132 |
|
2133 |
/**
|
2209 |
|
2210 |
}
|
2211 |
|
2212 |
+
/**
|
2213 |
+
* Recursively delete a directory including
|
2214 |
+
* all the files and sub-directories.
|
2215 |
+
*
|
2216 |
+
* @param string $dir
|
2217 |
+
* @return bool
|
2218 |
+
*/
|
2219 |
+
public static function rmdir_recursive( $dir ) {
|
2220 |
+
|
2221 |
+
if ( is_file( $dir ) )
|
2222 |
+
@unlink( $dir );
|
2223 |
+
|
2224 |
+
if ( ! is_dir( $dir ) )
|
2225 |
+
return false;
|
2226 |
+
|
2227 |
+
$files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
|
2228 |
+
|
2229 |
+
foreach ( $files as $file ) {
|
2230 |
+
|
2231 |
+
if ( $file->isDir() )
|
2232 |
+
@rmdir( $file->getPathname() );
|
2233 |
+
|
2234 |
+
else
|
2235 |
+
@unlink( $file->getPathname() );
|
2236 |
+
|
2237 |
+
}
|
2238 |
+
|
2239 |
+
@rmdir( $dir );
|
2240 |
+
|
2241 |
+
}
|
2242 |
+
|
2243 |
}
|
2244 |
|
2245 |
/**
|
wprp.integration.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Integration compatibility with hosts, plugins, and themes
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Get the likely web host for this site.
|
8 |
+
*/
|
9 |
+
function _wprp_integration_get_web_host() {
|
10 |
+
|
11 |
+
// WP Engine
|
12 |
+
if ( defined( 'IS_WPE' ) && IS_WPE )
|
13 |
+
return 'wpengine';
|
14 |
+
|
15 |
+
return 'unknown';
|
16 |
+
}
|
wprp.plugins.php
CHANGED
@@ -36,22 +36,36 @@ function _wprp_get_plugins() {
|
|
36 |
else
|
37 |
$current = get_option( 'update_plugins' );
|
38 |
|
39 |
-
|
|
|
40 |
|
41 |
-
|
42 |
|
43 |
if ( is_plugin_active( $plugin_file ) )
|
44 |
$plugins[$plugin_file]['active'] = true;
|
45 |
-
|
46 |
else
|
47 |
$plugins[$plugin_file]['active'] = false;
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
$plugins[$plugin_file]['slug'] = $current->response[$plugin_file]->slug;
|
53 |
|
54 |
} else {
|
|
|
55 |
$plugins[$plugin_file]['latest_version'] = $plugin['Version'];
|
56 |
|
57 |
}
|
@@ -68,7 +82,11 @@ function _wprp_get_plugins() {
|
|
68 |
* @param mixed $plugin
|
69 |
* @return array
|
70 |
*/
|
71 |
-
function _wprp_update_plugin( $
|
|
|
|
|
|
|
|
|
72 |
|
73 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
74 |
require_once ( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
@@ -76,46 +94,109 @@ function _wprp_update_plugin( $plugin ) {
|
|
76 |
|
77 |
// check for filesystem access
|
78 |
if ( ! _wpr_check_filesystem_access() )
|
79 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
$skin = new WPRP_Plugin_Upgrader_Skin();
|
82 |
$upgrader = new Plugin_Upgrader( $skin );
|
83 |
-
$is_active = is_plugin_active( $plugin );
|
84 |
|
85 |
-
//
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
// Do the upgrade
|
89 |
ob_start();
|
90 |
-
$result = $upgrader->upgrade( $
|
91 |
$data = ob_get_contents();
|
92 |
ob_clean();
|
93 |
|
|
|
|
|
|
|
94 |
if ( ! empty( $skin->error ) )
|
95 |
|
96 |
-
return
|
97 |
|
98 |
else if ( is_wp_error( $result ) )
|
99 |
|
100 |
-
return
|
101 |
|
102 |
else if ( ( ! $result && ! is_null( $result ) ) || $data )
|
103 |
|
104 |
-
return
|
105 |
|
106 |
// If the plugin was activited, we have to re-activate it
|
107 |
// but if activate_plugin() fatals, then we'll just have to return 500
|
108 |
if ( $is_active )
|
109 |
-
activate_plugin( $
|
110 |
|
111 |
return array( 'status' => 'success' );
|
112 |
}
|
113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
/**
|
115 |
* Install a plugin on this site
|
116 |
*/
|
117 |
function _wprp_install_plugin( $plugin, $args = array() ) {
|
118 |
|
|
|
|
|
|
|
119 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
120 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
121 |
include_once ABSPATH . 'wp-includes/update.php';
|
@@ -129,7 +210,7 @@ function _wprp_install_plugin( $plugin, $args = array() ) {
|
|
129 |
$api = plugins_api( 'plugin_information', $api_args );
|
130 |
|
131 |
if ( is_wp_error( $api ) )
|
132 |
-
return
|
133 |
|
134 |
$skin = new WPRP_Plugin_Upgrader_Skin();
|
135 |
$upgrader = new Plugin_Upgrader( $skin );
|
@@ -141,9 +222,9 @@ function _wprp_install_plugin( $plugin, $args = array() ) {
|
|
141 |
|
142 |
$result = $upgrader->install( $api->download_link );
|
143 |
if ( is_wp_error( $result ) )
|
144 |
-
return
|
145 |
else if ( ! $result )
|
146 |
-
return
|
147 |
|
148 |
return array( 'status' => 'success' );
|
149 |
}
|
@@ -155,7 +236,7 @@ function _wprp_activate_plugin( $plugin ) {
|
|
155 |
$result = activate_plugin( $plugin );
|
156 |
|
157 |
if ( is_wp_error( $result ) )
|
158 |
-
return
|
159 |
|
160 |
return array( 'status' => 'success' );
|
161 |
}
|
@@ -179,16 +260,19 @@ function _wprp_deactivate_plugin( $plugin ) {
|
|
179 |
function _wprp_uninstall_plugin( $plugin ) {
|
180 |
global $wp_filesystem;
|
181 |
|
|
|
|
|
|
|
182 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
183 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
184 |
include_once ABSPATH . 'wp-includes/update.php';
|
185 |
|
186 |
if ( ! _wpr_check_filesystem_access() || ! WP_Filesystem() )
|
187 |
-
return
|
188 |
|
189 |
$plugins_dir = $wp_filesystem->wp_plugins_dir();
|
190 |
if ( empty( $plugins_dir ) )
|
191 |
-
return
|
192 |
|
193 |
$plugins_dir = trailingslashit( $plugins_dir );
|
194 |
|
@@ -209,7 +293,7 @@ function _wprp_uninstall_plugin( $plugin ) {
|
|
209 |
}
|
210 |
return array( 'status' => 'success' );
|
211 |
} else {
|
212 |
-
return
|
213 |
}
|
214 |
|
215 |
}
|
36 |
else
|
37 |
$current = get_option( 'update_plugins' );
|
38 |
|
39 |
+
// Premium plugins that have adopted the ManageWP API report new plugins by this filter
|
40 |
+
$manage_wp_updates = apply_filters( 'mwp_premium_update_notification', array() );
|
41 |
|
42 |
+
foreach ( (array) $plugins as $plugin_file => $plugin ) {
|
43 |
|
44 |
if ( is_plugin_active( $plugin_file ) )
|
45 |
$plugins[$plugin_file]['active'] = true;
|
|
|
46 |
else
|
47 |
$plugins[$plugin_file]['active'] = false;
|
48 |
|
49 |
+
$manage_wp_plugin_update = false;
|
50 |
+
foreach( $manage_wp_updates as $manage_wp_update ) {
|
51 |
+
|
52 |
+
if ( ! empty( $manage_wp_update['Name'] ) && $plugin['Name'] == $manage_wp_update['Name'] )
|
53 |
+
$manage_wp_plugin_update = $manage_wp_update;
|
54 |
+
|
55 |
+
}
|
56 |
+
|
57 |
+
if ( $manage_wp_plugin_update ) {
|
58 |
+
|
59 |
+
$plugins[$plugin_file]['latest_version'] = $manage_wp_plugin_update['new_version'];
|
60 |
+
|
61 |
+
} else if ( isset( $current->response[$plugin_file] ) ) {
|
62 |
+
|
63 |
+
$plugins[$plugin_file]['latest_version'] = $current->response[$plugin_file]->new_version;
|
64 |
+
$plugins[$plugin_file]['latest_package'] = $current->response[$plugin_file]->package;
|
65 |
$plugins[$plugin_file]['slug'] = $current->response[$plugin_file]->slug;
|
66 |
|
67 |
} else {
|
68 |
+
|
69 |
$plugins[$plugin_file]['latest_version'] = $plugin['Version'];
|
70 |
|
71 |
}
|
82 |
* @param mixed $plugin
|
83 |
* @return array
|
84 |
*/
|
85 |
+
function _wprp_update_plugin( $plugin_file, $args ) {
|
86 |
+
global $wprp_zip_update;
|
87 |
+
|
88 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
89 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
90 |
|
91 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
92 |
require_once ( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
94 |
|
95 |
// check for filesystem access
|
96 |
if ( ! _wpr_check_filesystem_access() )
|
97 |
+
return new WP_Error( 'filesystem-not-writable', __( 'The filesystem is not writable with the supplied credentials', 'wpremote' ) );
|
98 |
+
|
99 |
+
$is_active = is_plugin_active( $plugin_file );
|
100 |
+
foreach( get_plugins() as $path => $maybe_plugin ) {
|
101 |
+
|
102 |
+
if ( $path == $plugin_file ) {
|
103 |
+
$plugin = $maybe_plugin;
|
104 |
+
break;
|
105 |
+
}
|
106 |
+
|
107 |
+
}
|
108 |
+
|
109 |
+
// Permit specifying a zip URL to update the plugin with
|
110 |
+
if ( ! empty( $args['zip_url'] ) ) {
|
111 |
+
|
112 |
+
$zip_url = $args['zip_url'];
|
113 |
+
|
114 |
+
} else {
|
115 |
+
|
116 |
+
// Check to see if this is a premium plugin that supports the ManageWP implementation
|
117 |
+
$manage_wp_updates = apply_filters( 'mwp_premium_perform_update', array() );
|
118 |
+
$manage_wp_plugin_update = false;
|
119 |
+
foreach( $manage_wp_updates as $manage_wp_update ) {
|
120 |
+
|
121 |
+
if ( ! empty( $manage_wp_update['Name'] )
|
122 |
+
&& $plugin['Name'] == $manage_wp_update['Name']
|
123 |
+
&& ! empty( $manage_wp_update['url'] ) ) {
|
124 |
+
$zip_url = $manage_wp_update['url'];
|
125 |
+
break;
|
126 |
+
}
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
}
|
131 |
|
132 |
$skin = new WPRP_Plugin_Upgrader_Skin();
|
133 |
$upgrader = new Plugin_Upgrader( $skin );
|
|
|
134 |
|
135 |
+
// Fake out the plugin upgrader with our package url
|
136 |
+
if ( ! empty( $zip_url ) ) {
|
137 |
+
$wprp_zip_update = array(
|
138 |
+
'plugin_file' => $plugin_file,
|
139 |
+
'package' => $zip_url,
|
140 |
+
);
|
141 |
+
add_filter( 'pre_site_transient_update_plugins', '_wprp_forcably_filter_update_plugins' );
|
142 |
+
} else {
|
143 |
+
wp_update_plugins();
|
144 |
+
}
|
145 |
|
146 |
// Do the upgrade
|
147 |
ob_start();
|
148 |
+
$result = $upgrader->upgrade( $plugin_file );
|
149 |
$data = ob_get_contents();
|
150 |
ob_clean();
|
151 |
|
152 |
+
if ( $manage_wp_plugin_update )
|
153 |
+
remove_filter( 'pre_site_transient_update_plugins', '_wprp_forcably_filter_update_plugins' );
|
154 |
+
|
155 |
if ( ! empty( $skin->error ) )
|
156 |
|
157 |
+
return new WP_Error( 'plugin-upgrader-skin', $upgrader->strings[$skin->error] );
|
158 |
|
159 |
else if ( is_wp_error( $result ) )
|
160 |
|
161 |
+
return $result;
|
162 |
|
163 |
else if ( ( ! $result && ! is_null( $result ) ) || $data )
|
164 |
|
165 |
+
return new WP_Error( 'plugin-update', __( 'Unknown error updating plugin.', 'wpremote' ) );
|
166 |
|
167 |
// If the plugin was activited, we have to re-activate it
|
168 |
// but if activate_plugin() fatals, then we'll just have to return 500
|
169 |
if ( $is_active )
|
170 |
+
activate_plugin( $plugin_file, '', false, true );
|
171 |
|
172 |
return array( 'status' => 'success' );
|
173 |
}
|
174 |
|
175 |
+
/**
|
176 |
+
* Filter `update_plugins` to produce a response it will understand
|
177 |
+
* so we can have the Upgrader skin handle the update
|
178 |
+
*/
|
179 |
+
function _wprp_forcably_filter_update_plugins() {
|
180 |
+
global $wprp_zip_update;
|
181 |
+
|
182 |
+
$current = new stdClass;
|
183 |
+
$current->response = array();
|
184 |
+
|
185 |
+
$plugin_file = $wprp_zip_update['plugin_file'];
|
186 |
+
$current->response[$plugin_file] = new stdClass;
|
187 |
+
$current->response[$plugin_file]->package = $wprp_zip_update['package'];
|
188 |
+
|
189 |
+
return $current;
|
190 |
+
}
|
191 |
+
|
192 |
/**
|
193 |
* Install a plugin on this site
|
194 |
*/
|
195 |
function _wprp_install_plugin( $plugin, $args = array() ) {
|
196 |
|
197 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
198 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
199 |
+
|
200 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
201 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
202 |
include_once ABSPATH . 'wp-includes/update.php';
|
210 |
$api = plugins_api( 'plugin_information', $api_args );
|
211 |
|
212 |
if ( is_wp_error( $api ) )
|
213 |
+
return $api;
|
214 |
|
215 |
$skin = new WPRP_Plugin_Upgrader_Skin();
|
216 |
$upgrader = new Plugin_Upgrader( $skin );
|
222 |
|
223 |
$result = $upgrader->install( $api->download_link );
|
224 |
if ( is_wp_error( $result ) )
|
225 |
+
return $result;
|
226 |
else if ( ! $result )
|
227 |
+
return new WP_Error( 'plugin-install', __( 'Unknown error installing plugin.', 'wpremote' ) );
|
228 |
|
229 |
return array( 'status' => 'success' );
|
230 |
}
|
236 |
$result = activate_plugin( $plugin );
|
237 |
|
238 |
if ( is_wp_error( $result ) )
|
239 |
+
return $result;
|
240 |
|
241 |
return array( 'status' => 'success' );
|
242 |
}
|
260 |
function _wprp_uninstall_plugin( $plugin ) {
|
261 |
global $wp_filesystem;
|
262 |
|
263 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
264 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
265 |
+
|
266 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
267 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
268 |
include_once ABSPATH . 'wp-includes/update.php';
|
269 |
|
270 |
if ( ! _wpr_check_filesystem_access() || ! WP_Filesystem() )
|
271 |
+
return new WP_Error( 'filesystem-not-writable', __( 'The filesystem is not writable with the supplied credentials', 'wpremote' ) );
|
272 |
|
273 |
$plugins_dir = $wp_filesystem->wp_plugins_dir();
|
274 |
if ( empty( $plugins_dir ) )
|
275 |
+
return new WP_Error( 'missing-plugin-dir', __( 'Unable to locate WordPress Plugin directory.' , 'wpremote' ) );
|
276 |
|
277 |
$plugins_dir = trailingslashit( $plugins_dir );
|
278 |
|
293 |
}
|
294 |
return array( 'status' => 'success' );
|
295 |
} else {
|
296 |
+
return new WP_Error( 'plugin-uninstall', __( 'Plugin uninstalled, but not deleted.', 'wpremote' ) );
|
297 |
}
|
298 |
|
299 |
}
|
wprp.themes.php
CHANGED
@@ -96,8 +96,11 @@ function _wprp_get_themes() {
|
|
96 |
*/
|
97 |
function _wprp_install_theme( $theme, $args = array() ) {
|
98 |
|
|
|
|
|
|
|
99 |
if ( wp_get_theme( $theme )->exists() )
|
100 |
-
return
|
101 |
|
102 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
103 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
@@ -112,7 +115,7 @@ function _wprp_install_theme( $theme, $args = array() ) {
|
|
112 |
$api = themes_api( 'theme_information', $api_args );
|
113 |
|
114 |
if ( is_wp_error( $api ) )
|
115 |
-
return
|
116 |
|
117 |
$skin = new WPRP_Theme_Upgrader_Skin();
|
118 |
$upgrader = new Theme_Upgrader( $skin );
|
@@ -126,7 +129,7 @@ function _wprp_install_theme( $theme, $args = array() ) {
|
|
126 |
if ( is_wp_error( $result ) )
|
127 |
return $result;
|
128 |
else if ( ! $result )
|
129 |
-
return
|
130 |
|
131 |
return array( 'status' => 'success' );
|
132 |
}
|
@@ -140,7 +143,7 @@ function _wprp_install_theme( $theme, $args = array() ) {
|
|
140 |
function _wprp_activate_theme( $theme ) {
|
141 |
|
142 |
if ( ! wp_get_theme( $theme )->exists() )
|
143 |
-
return
|
144 |
|
145 |
switch_theme( $theme );
|
146 |
return array( 'status' => 'success' );
|
@@ -154,13 +157,16 @@ function _wprp_activate_theme( $theme ) {
|
|
154 |
*/
|
155 |
function _wprp_update_theme( $theme ) {
|
156 |
|
|
|
|
|
|
|
157 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
158 |
require_once ( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
159 |
require_once WPRP_PLUGIN_PATH . 'inc/class-wprp-theme-upgrader-skin.php';
|
160 |
|
161 |
// check for filesystem access
|
162 |
if ( ! _wpr_check_filesystem_access() )
|
163 |
-
return
|
164 |
|
165 |
$skin = new WPRP_Theme_Upgrader_Skin();
|
166 |
$upgrader = new Theme_Upgrader( $skin );
|
@@ -171,14 +177,17 @@ function _wprp_update_theme( $theme ) {
|
|
171 |
$data = ob_get_contents();
|
172 |
ob_clean();
|
173 |
|
174 |
-
if (
|
175 |
-
return array( 'status' => 'error', 'error' => 'file_permissions_error' );
|
176 |
|
177 |
-
|
178 |
-
return array( 'status' => 'error', 'error' => $result->get_error_code() );
|
179 |
|
180 |
-
if ( $
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
182 |
|
183 |
return array( 'status' => 'success' );
|
184 |
|
@@ -193,26 +202,29 @@ function _wprp_update_theme( $theme ) {
|
|
193 |
function _wprp_delete_theme( $theme ) {
|
194 |
global $wp_filesystem;
|
195 |
|
|
|
|
|
|
|
196 |
if ( ! wp_get_theme( $theme )->exists() )
|
197 |
-
return
|
198 |
|
199 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
200 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
201 |
include_once ABSPATH . 'wp-includes/update.php';
|
202 |
|
203 |
if ( ! _wpr_check_filesystem_access() || ! WP_Filesystem() )
|
204 |
-
return
|
205 |
|
206 |
$themes_dir = $wp_filesystem->wp_themes_dir();
|
207 |
if ( empty( $themes_dir ) )
|
208 |
-
return
|
209 |
|
210 |
$themes_dir = trailingslashit( $themes_dir );
|
211 |
$theme_dir = trailingslashit( $themes_dir . $theme );
|
212 |
$deleted = $wp_filesystem->delete( $theme_dir, true );
|
213 |
|
214 |
if ( ! $deleted )
|
215 |
-
return
|
216 |
|
217 |
// Force refresh of theme update information
|
218 |
delete_site_transient('update_themes');
|
96 |
*/
|
97 |
function _wprp_install_theme( $theme, $args = array() ) {
|
98 |
|
99 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
100 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
101 |
+
|
102 |
if ( wp_get_theme( $theme )->exists() )
|
103 |
+
return new WP_Error( 'theme-installed', __( 'Theme is already installed.' ) );
|
104 |
|
105 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
106 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
115 |
$api = themes_api( 'theme_information', $api_args );
|
116 |
|
117 |
if ( is_wp_error( $api ) )
|
118 |
+
return $api;
|
119 |
|
120 |
$skin = new WPRP_Theme_Upgrader_Skin();
|
121 |
$upgrader = new Theme_Upgrader( $skin );
|
129 |
if ( is_wp_error( $result ) )
|
130 |
return $result;
|
131 |
else if ( ! $result )
|
132 |
+
return new WP_Error( 'unknown-install-error', __( 'Unknown error installing theme.', 'wpremote' ) );
|
133 |
|
134 |
return array( 'status' => 'success' );
|
135 |
}
|
143 |
function _wprp_activate_theme( $theme ) {
|
144 |
|
145 |
if ( ! wp_get_theme( $theme )->exists() )
|
146 |
+
return new WP_Error( 'theme-not-installed', __( 'Theme is not installed.', 'wpremote' ) );
|
147 |
|
148 |
switch_theme( $theme );
|
149 |
return array( 'status' => 'success' );
|
157 |
*/
|
158 |
function _wprp_update_theme( $theme ) {
|
159 |
|
160 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
161 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
162 |
+
|
163 |
include_once ( ABSPATH . 'wp-admin/includes/admin.php' );
|
164 |
require_once ( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
165 |
require_once WPRP_PLUGIN_PATH . 'inc/class-wprp-theme-upgrader-skin.php';
|
166 |
|
167 |
// check for filesystem access
|
168 |
if ( ! _wpr_check_filesystem_access() )
|
169 |
+
return new WP_Error( 'filesystem-not-writable', __( 'The filesystem is not writable with the supplied credentials', 'wpremote' ) );
|
170 |
|
171 |
$skin = new WPRP_Theme_Upgrader_Skin();
|
172 |
$upgrader = new Theme_Upgrader( $skin );
|
177 |
$data = ob_get_contents();
|
178 |
ob_clean();
|
179 |
|
180 |
+
if ( ! empty( $skin->error ) )
|
|
|
181 |
|
182 |
+
return new WP_Error( 'theme-upgrader-skin', $upgrader->strings[$skin->error] );
|
|
|
183 |
|
184 |
+
else if ( is_wp_error( $result ) )
|
185 |
+
|
186 |
+
return $result;
|
187 |
+
|
188 |
+
else if ( ( ! $result && ! is_null( $result ) ) || $data )
|
189 |
+
|
190 |
+
return new WP_Error( 'theme-update', __( 'Unknown error updating theme.', 'wpremote' ) );
|
191 |
|
192 |
return array( 'status' => 'success' );
|
193 |
|
202 |
function _wprp_delete_theme( $theme ) {
|
203 |
global $wp_filesystem;
|
204 |
|
205 |
+
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
|
206 |
+
return new WP_Error( 'disallow-file-mods', __( "File modification is disabled with the DISALLOW_FILE_MODS constant.", 'wpremote' ) );
|
207 |
+
|
208 |
if ( ! wp_get_theme( $theme )->exists() )
|
209 |
+
return new WP_Error( 'theme-missing', __( 'Theme is not installed.', 'wpremote' ) );
|
210 |
|
211 |
include_once ABSPATH . 'wp-admin/includes/admin.php';
|
212 |
include_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
213 |
include_once ABSPATH . 'wp-includes/update.php';
|
214 |
|
215 |
if ( ! _wpr_check_filesystem_access() || ! WP_Filesystem() )
|
216 |
+
return new WP_Error( 'filesystem-not-writable', __( 'The filesystem is not writable with the supplied credentials', 'wpremote' ) );
|
217 |
|
218 |
$themes_dir = $wp_filesystem->wp_themes_dir();
|
219 |
if ( empty( $themes_dir ) )
|
220 |
+
return new WP_Error( 'theme-dir-missing', __( 'Unable to locate WordPress theme directory', 'wpremote' ) );
|
221 |
|
222 |
$themes_dir = trailingslashit( $themes_dir );
|
223 |
$theme_dir = trailingslashit( $themes_dir . $theme );
|
224 |
$deleted = $wp_filesystem->delete( $theme_dir, true );
|
225 |
|
226 |
if ( ! $deleted )
|
227 |
+
return new WP_Error( 'theme-delete', sprintf( __( 'Could not fully delete the theme: %s.', 'wpremote' ), $theme ) );
|
228 |
|
229 |
// Force refresh of theme update information
|
230 |
delete_site_transient('update_themes');
|