Version Description
- New: Performance improvement increase db query limit to 5000
- New: Detect automatically if WordPress is installed in sub folder
- Tweak: Tested up to WP 4.9.4
- Fix: Updating from an old version 1.1.6 < to latest version deletes the staging sites listing table
- Fix: Reduce memory size of the logging window to prevent browser timeouts
- Fix: Can not copy db table if table name contains the db prefix multiple times
- Fix: Some excluded folders are not ignored during copy process
- Fix: mod_security is causing script termination
- Fix: Skip directory listings for symlinks
Download this release
Release Info
Developer | ReneHermi |
Plugin | WP Staging – DB & File Duplicator & Migration |
Version | 2.1.9 |
Comparing to | |
See all releases |
Code changes from version 2.1.8 to 2.1.9
- apps/Backend/Administrator.php +695 -695
- apps/Backend/Modules/Jobs/Cancel.php +74 -74
- apps/Backend/Modules/Jobs/CancelUpdate.php +90 -90
- apps/Backend/Modules/Jobs/Cloning.php +249 -249
- apps/Backend/Modules/Jobs/Data.php +459 -408
- apps/Backend/Modules/Jobs/Database.php +264 -262
- apps/Backend/Modules/Jobs/Delete.php +497 -497
- apps/Backend/Modules/Jobs/Directories.php +428 -451
- apps/Backend/Modules/Jobs/Files.php +366 -365
- apps/Backend/Modules/Jobs/Finish.php +120 -261
- apps/Backend/Modules/Jobs/Job.php +487 -484
- apps/Backend/Modules/Jobs/JobExecutable.php +111 -111
- apps/Backend/Modules/Jobs/Scan.php +406 -401
- apps/Backend/Modules/Jobs/Updating.php +248 -261
- apps/Backend/Modules/SystemInfo.php +512 -512
- apps/Backend/Modules/Views/Forms/Settings.php +219 -219
- apps/Backend/Notices/Notices.php +154 -154
- apps/Backend/Upgrade/Upgrade.php +221 -229
- apps/Backend/public/css/wpstg-admin.css +783 -783
- apps/Backend/public/js/wpstg-admin-rating.js +31 -31
- apps/Backend/public/js/wpstg-admin.js +1177 -1260
- apps/Backend/views/_includes/messages/beta.php +19 -19
- apps/Backend/views/_includes/messages/rating.php +30 -30
- apps/Backend/views/_includes/messages/wp-version-compatible-message.php +12 -12
- apps/Backend/views/clone/ajax/scan.php +128 -128
- apps/Backend/views/clone/ajax/single-overview.php +55 -55
- apps/Backend/views/clone/ajax/start.php +112 -112
- apps/Backend/views/clone/ajax/update.php +45 -45
- apps/Backend/views/settings/index.php +1 -1
- apps/Core/Iterators/RecursiveDirectoryIterator.php +52 -52
- apps/Core/Iterators/RecursiveFilterExclude.php +23 -23
- apps/Core/Iterators/RecursiveFilterNewLine.php +21 -21
- apps/Core/Utils/Cache.php +211 -211
- apps/Core/Utils/Strings.php +27 -0
- apps/Core/WPStaging.php +429 -429
- package-lock.json +0 -3333
- readme.txt +314 -301
- uninstall.php +89 -89
- wp-staging.php +91 -91
apps/Backend/Administrator.php
CHANGED
@@ -1,695 +1,695 @@
|
|
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;
|
11 |
-
use WPStaging\Backend\Modules\Jobs\CancelUpdate;
|
12 |
-
use WPStaging\Backend\Modules\Jobs\Cloning;
|
13 |
-
use WPStaging\Backend\Modules\Jobs\Updating;
|
14 |
-
use WPStaging\Backend\Modules\Jobs\Data;
|
15 |
-
use WPStaging\Backend\Modules\Jobs\Database;
|
16 |
-
use WPStaging\Backend\Modules\Jobs\Delete;
|
17 |
-
use WPStaging\Backend\Modules\Jobs\Files;
|
18 |
-
use WPStaging\Backend\Modules\Jobs\Scan;
|
19 |
-
use WPStaging\Backend\Modules\Jobs\Logs;
|
20 |
-
use WPStaging\Backend\Modules\Optimizer;
|
21 |
-
use WPStaging\Backend\Modules\SystemInfo;
|
22 |
-
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
23 |
-
use WPStaging\Backend\Notices\Notices;
|
24 |
-
use WPStaging\DI\InjectionAware;
|
25 |
-
use WPStaging\Backend\Modules\Views\Forms\Settings as FormSettings;
|
26 |
-
use WPStaging\Backend\Activation;
|
27 |
-
use WPStaging\WPStaging;
|
28 |
-
use WPStaging\Backend\Pro\Modules\Jobs\Processing;
|
29 |
-
use WPStaging\Backend\Pro\Licensing;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Class Administrator
|
33 |
-
* @package WPStaging\Backend
|
34 |
-
*/
|
35 |
-
class Administrator extends InjectionAware {
|
36 |
-
|
37 |
-
/**
|
38 |
-
* @var string
|
39 |
-
*/
|
40 |
-
private $path;
|
41 |
-
|
42 |
-
/**
|
43 |
-
* @var string
|
44 |
-
*/
|
45 |
-
private $url;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Initialize class
|
49 |
-
*/
|
50 |
-
public function initialize() {
|
51 |
-
$this->defineHooks();
|
52 |
-
|
53 |
-
// Path to backend
|
54 |
-
$this->path = plugin_dir_path( __FILE__ );
|
55 |
-
|
56 |
-
// URL to public backend folder
|
57 |
-
$this->url = plugin_dir_url( __FILE__ ) . "public/";
|
58 |
-
|
59 |
-
// Load plugins meta data
|
60 |
-
$this->loadMeta();
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Load plugn meta data
|
65 |
-
*/
|
66 |
-
public function loadMeta() {
|
67 |
-
$run = new \WPStaging\Backend\Pluginmeta\Pluginmeta();
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Define Hooks
|
72 |
-
*/
|
73 |
-
private function defineHooks() {
|
74 |
-
// Get loader
|
75 |
-
$loader = $this->di->get( "loader" );
|
76 |
-
|
77 |
-
$Activation = new \WPStaging\Backend\Activation\Activation();
|
78 |
-
|
79 |
-
$Welcome = new Activation\Welcome();
|
80 |
-
|
81 |
-
$loader->addAction( "activated_plugin", $Activation, 'deactivate_other_instances' );
|
82 |
-
$loader->addAction( "admin_menu", $this, "addMenu", 10 );
|
83 |
-
$loader->addAction( "admin_init", $this, "setOptionFormElements" );
|
84 |
-
$loader->addAction( "admin_init", $this, "upgrade" );
|
85 |
-
$loader->addAction( "admin_post_wpstg_download_sysinfo", $this, "systemInfoDownload" );
|
86 |
-
$loader->addAction( "admin_post_wpstg_export", $this, "export" );
|
87 |
-
$loader->addAction( "admin_post_wpstg_import_settings", $this, "import" );
|
88 |
-
$loader->addAction( "admin_notices", $this, "messages" );
|
89 |
-
|
90 |
-
// Ajax Requests
|
91 |
-
$loader->addAction( "wp_ajax_wpstg_overview", $this, "ajaxOverview" );
|
92 |
-
$loader->addAction( "wp_ajax_wpstg_scanning", $this, "ajaxScan" );
|
93 |
-
$loader->addAction( "wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName" );
|
94 |
-
//$loader->addAction( "wp_ajax_wpstg_update_struc", $this, "ajaxStartUpdate" );
|
95 |
-
$loader->addAction( "wp_ajax_wpstg_update", $this, "ajaxUpdateProcess" );
|
96 |
-
$loader->addAction( "wp_ajax_wpstg_cloning", $this, "ajaxStartClone" );
|
97 |
-
$loader->addAction( "wp_ajax_wpstg_clone_database", $this, "ajaxCloneDatabase" );
|
98 |
-
$loader->addAction( "wp_ajax_wpstg_clone_prepare_directories", $this, "ajaxPrepareDirectories" );
|
99 |
-
$loader->addAction( "wp_ajax_wpstg_clone_files", $this, "ajaxCopyFiles" );
|
100 |
-
$loader->addAction( "wp_ajax_wpstg_clone_replace_data", $this, "ajaxReplaceData" );
|
101 |
-
$loader->addAction( "wp_ajax_wpstg_clone_finish", $this, "ajaxFinish" );
|
102 |
-
$loader->addAction( "wp_ajax_wpstg_confirm_delete_clone", $this, "ajaxDeleteConfirmation" );
|
103 |
-
$loader->addAction( "wp_ajax_wpstg_delete_clone", $this, "ajaxDeleteClone" );
|
104 |
-
$loader->addAction( "wp_ajax_wpstg_cancel_clone", $this, "ajaxCancelClone" );
|
105 |
-
$loader->addAction( "wp_ajax_wpstg_cancel_update", $this, "ajaxCancelUpdate" );
|
106 |
-
$loader->addAction( "wp_ajax_wpstg_hide_poll", $this, "ajaxHidePoll" );
|
107 |
-
$loader->addAction( "wp_ajax_wpstg_hide_rating", $this, "ajaxHideRating" );
|
108 |
-
$loader->addAction( "wp_ajax_wpstg_hide_beta", $this, "ajaxHideBeta" );
|
109 |
-
$loader->addAction( "wp_ajax_wpstg_logs", $this, "ajaxLogs" );
|
110 |
-
$loader->addAction( "wp_ajax_wpstg_check_disk_space", $this, "ajaxCheckFreeSpace" );
|
111 |
-
|
112 |
-
// Ajax hooks pro Version
|
113 |
-
$loader->addAction( "wp_ajax_wpstg_scan", $this, "ajaxPushScan" );
|
114 |
-
$loader->addAction( "wp_ajax_wpstg_push_processing", $this, "ajaxPushProcessing" );
|
115 |
-
//$loader->addAction( "wp_ajax_wpstg_copy_database", $this, "ajaxCopyDatabase" );
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Register options form elements
|
120 |
-
*/
|
121 |
-
public function setOptionFormElements() {
|
122 |
-
register_setting( "wpstg_settings", "wpstg_settings", array($this, "sanitizeOptions") );
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Upgrade routine
|
127 |
-
*/
|
128 |
-
public function upgrade() {
|
129 |
-
$upgrade = new Upgrade\Upgrade();
|
130 |
-
$upgrade->doUpgrade();
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Sanitize options data and delete the cache
|
135 |
-
* @param array $data
|
136 |
-
* @return array
|
137 |
-
*/
|
138 |
-
public function sanitizeOptions( $data = array() ) {
|
139 |
-
$sanitized = $this->sanitizeData( $data );
|
140 |
-
|
141 |
-
add_settings_error( "wpstg-notices", '', __( "Settings updated.", "wpstg" ), "updated" );
|
142 |
-
|
143 |
-
// Return sanitized data
|
144 |
-
//return $sanitized;
|
145 |
-
return apply_filters( "wpstg-settings", $sanitized, $data );
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* @param array $data
|
150 |
-
* @return array
|
151 |
-
*/
|
152 |
-
private function sanitizeData( $data = array() ) {
|
153 |
-
$sanitized = array();
|
154 |
-
|
155 |
-
foreach ( $data as $key => $value ) {
|
156 |
-
$sanitized[$key] = (is_array( $value )) ? $this->sanitizeData( $value ) : htmlspecialchars( $value );
|
157 |
-
}
|
158 |
-
|
159 |
-
return $sanitized;
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Add Admin Menu(s)
|
164 |
-
*/
|
165 |
-
public function addMenu() {
|
166 |
-
|
167 |
-
$logo = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGw9Im5vbmUiPgo8Zz48Zz48cGF0aCBzdHlsZT0iZmlsbDojZmZmIiAgZD0iTTEzNy42LDU2MS4zSDEzLjhIMTB2MzA2LjNsOTAuNy04My40QzE4OS42LDkwOC43LDMzNS4zLDk5MCw1MDAsOTkwYzI0OS45LDAsNDU2LjEtMTg3LjEsNDg2LjItNDI4LjhIODYyLjRDODMzLjMsNzM1LjEsNjgyLjEsODY3LjUsNTAwLDg2Ny41Yy0xMjksMC0yNDIuNS02Ni41LTMwOC4xLTE2Ny4ybDE1MS4zLTEzOS4xSDEzNy42eiIvPjxwYXRoIHN0eWxlPSJmaWxsOiNmZmYiICBkPSJNNTAwLDEwQzI1MC4xLDEwLDQzLjksMTk3LjEsMTMuOCw0MzguOGgxMjMuOEMxNjYuNywyNjQuOSwzMTcuOSwxMzIuNSw1MDAsMTMyLjVjMTMyLjksMCwyNDkuMyw3MC41LDMxMy44LDE3Ni4yTDY4My44LDQzOC44aDEyMi41aDU2LjJoMTIzLjhoMy44VjEzMi41bC04Ny43LDg3LjdDODEzLjgsOTMuMSw2NjYuNiwxMCw1MDAsMTB6Ii8+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvZz4KPC9zdmc+';
|
168 |
-
|
169 |
-
// Main WP Staging Menu
|
170 |
-
add_menu_page(
|
171 |
-
"WP-Staging", __( "WP Staging", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage"), $logo
|
172 |
-
);
|
173 |
-
|
174 |
-
// Page: Clone
|
175 |
-
add_submenu_page(
|
176 |
-
"wpstg_clone", __( "WP Staging Jobs", "wpstg" ), __( "Start", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage")
|
177 |
-
);
|
178 |
-
|
179 |
-
// Page: Settings
|
180 |
-
add_submenu_page(
|
181 |
-
"wpstg_clone", __( "WP Staging Settings", "wpstg" ), __( "Settings", "wpstg" ), "manage_options", "wpstg-settings", array($this, "getSettingsPage")
|
182 |
-
);
|
183 |
-
|
184 |
-
// Page: Tools
|
185 |
-
add_submenu_page(
|
186 |
-
"wpstg_clone", __( "WP Staging Tools", "wpstg" ), __( "Tools", "wpstg" ), "manage_options", "wpstg-tools", array($this, "getToolsPage")
|
187 |
-
);
|
188 |
-
// Page: Tools
|
189 |
-
add_submenu_page(
|
190 |
-
"wpstg_clone", __( "WP Staging Welcome", "wpstg" ), __( "Get WP Staging Pro", "wpstg" ), "manage_options", "wpstg-welcome", array($this, "getWelcomePage")
|
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 |
-
* Welcome Page
|
232 |
-
*/
|
233 |
-
public function getWelcomePage() {
|
234 |
-
require_once "{$this->path}views/welcome/welcome.php";
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* Tools Page
|
239 |
-
*/
|
240 |
-
public function getToolsPage() {
|
241 |
-
// Tabs
|
242 |
-
$tabs = new Tabs( array(
|
243 |
-
"import_export" => __( "Import/Export", "wpstg" ),
|
244 |
-
"system_info" => __( "System Info", "wpstg" )
|
245 |
-
) );
|
246 |
-
|
247 |
-
$this->di->set( "tabs", $tabs );
|
248 |
-
|
249 |
-
$this->di->set( "systemInfo", new SystemInfo( $this->di ) );
|
250 |
-
|
251 |
-
require_once "{$this->path}views/tools/index.php";
|
252 |
-
}
|
253 |
-
|
254 |
-
/**
|
255 |
-
* System Information Download
|
256 |
-
*/
|
257 |
-
public function systemInfoDownload() {
|
258 |
-
if( !current_user_can( "update_plugins" ) ) {
|
259 |
-
return;
|
260 |
-
}
|
261 |
-
|
262 |
-
nocache_headers();
|
263 |
-
header( "Content-Type: text/plain" );
|
264 |
-
header( "Content-Disposition: attachment; filename='wpstg-system-info.txt'" );
|
265 |
-
echo wp_strip_all_tags( new SystemInfo( $this->di ) );
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* Import JSON settings file
|
270 |
-
*/
|
271 |
-
public function import() {
|
272 |
-
if( empty( $_POST["wpstg_import_nonce"] ) ) {
|
273 |
-
return;
|
274 |
-
}
|
275 |
-
|
276 |
-
if( !wp_verify_nonce( $_POST["wpstg_import_nonce"], "wpstg_import_nonce" ) ) {
|
277 |
-
return;
|
278 |
-
}
|
279 |
-
|
280 |
-
if( !current_user_can( "update_plugins" ) ) {
|
281 |
-
return;
|
282 |
-
}
|
283 |
-
|
284 |
-
$fileExtension = explode( '.', $_FILES["import_file"]["name"] );
|
285 |
-
$fileExtension = end( $fileExtension );
|
286 |
-
if( "json" !== $fileExtension ) {
|
287 |
-
wp_die( "Please upload a valid .json file", "wpstg" );
|
288 |
-
}
|
289 |
-
|
290 |
-
|
291 |
-
$importFile = $_FILES["import_file"]["tmp_name"];
|
292 |
-
|
293 |
-
if( empty( $importFile ) ) {
|
294 |
-
wp_die( __( "Please upload a file to import", "wpstg" ) );
|
295 |
-
}
|
296 |
-
|
297 |
-
update_option( "wpstg_settings", json_decode( file_get_contents( $importFile, true ) ) );
|
298 |
-
|
299 |
-
wp_safe_redirect( admin_url( "admin.php?page=wpstg-tools&wpstg-message=settings-imported" ) );
|
300 |
-
|
301 |
-
return;
|
302 |
-
}
|
303 |
-
|
304 |
-
/**
|
305 |
-
* Export settings to JSON file
|
306 |
-
*/
|
307 |
-
public function export() {
|
308 |
-
if( empty( $_POST["wpstg_export_nonce"] ) ) {
|
309 |
-
return;
|
310 |
-
}
|
311 |
-
|
312 |
-
if( !wp_verify_nonce( $_POST["wpstg_export_nonce"], "wpstg_export_nonce" ) ) {
|
313 |
-
return;
|
314 |
-
}
|
315 |
-
|
316 |
-
if( !current_user_can( "manage_options" ) ) {
|
317 |
-
return;
|
318 |
-
}
|
319 |
-
|
320 |
-
$settings = get_option( "wpstg_settings", array() );
|
321 |
-
|
322 |
-
ignore_user_abort( true );
|
323 |
-
|
324 |
-
if( !in_array( "set_time_limit", explode( ',', ini_get( "disable_functions" ) ) ) && !@ini_get( "safe_mode" ) ) {
|
325 |
-
set_time_limit( 0 );
|
326 |
-
}
|
327 |
-
|
328 |
-
$fileName = apply_filters( "wpstg_settings_export_filename", "wpstg-settings-export-" . date( "m-d-Y" ) ) . ".json";
|
329 |
-
|
330 |
-
nocache_headers();
|
331 |
-
header( "Content-Type: application/json; charset=utf-8" );
|
332 |
-
header( "Content-Disposition: attachment; filename={$fileName}" );
|
333 |
-
header( "Expires: 0" );
|
334 |
-
|
335 |
-
echo json_encode( $settings );
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* Render a view file
|
340 |
-
* @param string $file
|
341 |
-
* @param array $vars
|
342 |
-
* @return string
|
343 |
-
*/
|
344 |
-
public function render( $file, $vars = array() ) {
|
345 |
-
$fullPath = $this->path . "views" . DIRECTORY_SEPARATOR;
|
346 |
-
$fullPath = str_replace( array('/', "\\"), DIRECTORY_SEPARATOR, $fullPath . $file . ".php" );
|
347 |
-
|
348 |
-
if( !file_exists( $fullPath ) || !is_readable( $fullPath ) ) {
|
349 |
-
return "Can't render : {$fullPath} either file doesn't exist or can't read it";
|
350 |
-
}
|
351 |
-
|
352 |
-
$contents = @file_get_contents( $fullPath );
|
353 |
-
|
354 |
-
// Variables are set
|
355 |
-
if( count( $vars ) > 0 ) {
|
356 |
-
$vars = array_combine(
|
357 |
-
array_map( function ($key) {
|
358 |
-
return "{{" . $key . "}}";
|
359 |
-
}, array_keys( $vars )
|
360 |
-
), $vars
|
361 |
-
);
|
362 |
-
|
363 |
-
$contents = str_replace( array_keys( $vars ), array_values( $vars ), $contents );
|
364 |
-
}
|
365 |
-
|
366 |
-
return $contents;
|
367 |
-
}
|
368 |
-
|
369 |
-
/**
|
370 |
-
* Ajax Overview
|
371 |
-
*/
|
372 |
-
public function ajaxOverview() {
|
373 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
374 |
-
|
375 |
-
// Existing clones
|
376 |
-
$availableClones = get_option( "wpstg_existing_clones_beta", array() );
|
377 |
-
|
378 |
-
// Get license data
|
379 |
-
$license = get_option( 'wpstg_license_status' );
|
380 |
-
|
381 |
-
|
382 |
-
if( \WPStaging\WPStaging::getSlug() === 'wp-staging-pro' ) {
|
383 |
-
require_once "{$this->path}Pro/views/single-overview-pro.php";
|
384 |
-
} else {
|
385 |
-
require_once "{$this->path}views/clone/ajax/single-overview.php";
|
386 |
-
}
|
387 |
-
|
388 |
-
wp_die();
|
389 |
-
}
|
390 |
-
|
391 |
-
/**
|
392 |
-
* Ajax Scan
|
393 |
-
*/
|
394 |
-
public function ajaxScan() {
|
395 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
396 |
-
|
397 |
-
// Scan
|
398 |
-
$scan = new Scan();
|
399 |
-
$scan->start();
|
400 |
-
|
401 |
-
// Get Options
|
402 |
-
$options = $scan->getOptions();
|
403 |
-
|
404 |
-
require_once "{$this->path}views/clone/ajax/scan.php";
|
405 |
-
|
406 |
-
wp_die();
|
407 |
-
}
|
408 |
-
|
409 |
-
/**
|
410 |
-
* Ajax Check Clone Name
|
411 |
-
*/
|
412 |
-
public function ajaxCheckCloneName() {
|
413 |
-
$cloneName = sanitize_key( $_POST["cloneID"] );
|
414 |
-
$cloneNameLength = strlen( $cloneName );
|
415 |
-
$clones = get_option( "wpstg_existing_clones_beta", array() );
|
416 |
-
|
417 |
-
// Check clone name length
|
418 |
-
if( $cloneNameLength < 1 || $cloneNameLength > 16 ) {
|
419 |
-
echo wp_send_json( array(
|
420 |
-
"status" => "failed",
|
421 |
-
"message" => "Clone name must be between 1 - 16 characters"
|
422 |
-
) );
|
423 |
-
} elseif( array_key_exists( $cloneName, $clones ) ) {
|
424 |
-
echo wp_send_json( array(
|
425 |
-
"status" => "failed",
|
426 |
-
"message" => "Clone name is already in use, please choose an another clone name"
|
427 |
-
) );
|
428 |
-
}
|
429 |
-
|
430 |
-
echo wp_send_json( array("status" => "success") );
|
431 |
-
}
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
/**
|
437 |
-
* Ajax Start Updating Clone (Basically just layout and saving data)
|
438 |
-
*/
|
439 |
-
// public function ajaxStartUpdate() {
|
440 |
-
// check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
441 |
-
//
|
442 |
-
// $cloning = new Updating();
|
443 |
-
//
|
444 |
-
// if( !$cloning->save() ) {
|
445 |
-
// wp_die('can not save clone data');
|
446 |
-
// }
|
447 |
-
//
|
448 |
-
// require_once "{$this->path}views/clone/ajax/update.php";
|
449 |
-
//
|
450 |
-
// wp_die();
|
451 |
-
// }
|
452 |
-
/**
|
453 |
-
* Ajax Start Updating Clone (Basically just layout and saving data)
|
454 |
-
*/
|
455 |
-
public function ajaxUpdateProcess() {
|
456 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
457 |
-
|
458 |
-
$cloning = new Updating();
|
459 |
-
|
460 |
-
if( !$cloning->save() ) {
|
461 |
-
wp_die('can not save clone data');
|
462 |
-
}
|
463 |
-
|
464 |
-
require_once "{$this->path}views/clone/ajax/update.php";
|
465 |
-
|
466 |
-
wp_die();
|
467 |
-
|
468 |
-
//wp_send_json( $cloning->start() );
|
469 |
-
}
|
470 |
-
/**
|
471 |
-
* Ajax Start Clone (Basically just layout and saving data)
|
472 |
-
*/
|
473 |
-
public function ajaxStartClone() {
|
474 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
475 |
-
|
476 |
-
$cloning = new Cloning();
|
477 |
-
|
478 |
-
if( !$cloning->save() ) {
|
479 |
-
wp_die('can not save clone data');
|
480 |
-
}
|
481 |
-
|
482 |
-
require_once "{$this->path}views/clone/ajax/start.php";
|
483 |
-
|
484 |
-
wp_die();
|
485 |
-
}
|
486 |
-
|
487 |
-
/**
|
488 |
-
* Ajax Clone Database
|
489 |
-
*/
|
490 |
-
public function ajaxCloneDatabase() {
|
491 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
492 |
-
|
493 |
-
$cloning = new Cloning();
|
494 |
-
|
495 |
-
wp_send_json( $cloning->start() );
|
496 |
-
}
|
497 |
-
|
498 |
-
/**
|
499 |
-
* Ajax Prepare Directories (get listing of files)
|
500 |
-
*/
|
501 |
-
public function ajaxPrepareDirectories() {
|
502 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
503 |
-
|
504 |
-
$cloning = new Cloning();
|
505 |
-
|
506 |
-
wp_send_json( $cloning->start() );
|
507 |
-
}
|
508 |
-
|
509 |
-
/**
|
510 |
-
* Ajax Clone Files
|
511 |
-
*/
|
512 |
-
public function ajaxCopyFiles() {
|
513 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
514 |
-
|
515 |
-
$cloning = new Cloning();
|
516 |
-
|
517 |
-
wp_send_json( $cloning->start() );
|
518 |
-
}
|
519 |
-
|
520 |
-
/**
|
521 |
-
* Ajax Replace Data
|
522 |
-
*/
|
523 |
-
public function ajaxReplaceData() {
|
524 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
525 |
-
|
526 |
-
$cloning = new Cloning();
|
527 |
-
|
528 |
-
wp_send_json( $cloning->start() );
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Ajax Finish
|
533 |
-
*/
|
534 |
-
public function ajaxFinish() {
|
535 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
536 |
-
|
537 |
-
$cloning = new Cloning();
|
538 |
-
|
539 |
-
wp_send_json( $cloning->start() );
|
540 |
-
}
|
541 |
-
|
542 |
-
/**
|
543 |
-
* Ajax Delete Confirmation
|
544 |
-
*/
|
545 |
-
public function ajaxDeleteConfirmation() {
|
546 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
547 |
-
|
548 |
-
$delete = new Delete();
|
549 |
-
$delete->setData();
|
550 |
-
|
551 |
-
$clone = $delete->getClone();
|
552 |
-
|
553 |
-
require_once "{$this->path}views/clone/ajax/delete-confirmation.php";
|
554 |
-
|
555 |
-
wp_die();
|
556 |
-
}
|
557 |
-
|
558 |
-
/**
|
559 |
-
* Delete clone
|
560 |
-
*/
|
561 |
-
public function ajaxDeleteClone() {
|
562 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
563 |
-
|
564 |
-
$delete = new Delete();
|
565 |
-
wp_send_json( $delete->start() );
|
566 |
-
}
|
567 |
-
|
568 |
-
/**
|
569 |
-
* Delete clone
|
570 |
-
*/
|
571 |
-
public function ajaxCancelClone() {
|
572 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
573 |
-
|
574 |
-
$cancel = new Cancel();
|
575 |
-
wp_send_json( $cancel->start() );
|
576 |
-
}
|
577 |
-
|
578 |
-
/**
|
579 |
-
* Cancel updating process / Do not delete clone!
|
580 |
-
*/
|
581 |
-
public function ajaxCancelUpdate() {
|
582 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
583 |
-
|
584 |
-
$cancel = new CancelUpdate();
|
585 |
-
wp_send_json( $cancel->start() );
|
586 |
-
}
|
587 |
-
|
588 |
-
/**
|
589 |
-
* Admin Messages
|
590 |
-
*/
|
591 |
-
public function messages() {
|
592 |
-
$notice = new Notices( $this->path, $this->url );
|
593 |
-
|
594 |
-
$run = $notice->messages();
|
595 |
-
}
|
596 |
-
|
597 |
-
/**
|
598 |
-
* Ajax Hide Poll
|
599 |
-
* @return mixed boolean | json
|
600 |
-
*/
|
601 |
-
public function ajaxHidePoll() {
|
602 |
-
if( false !== update_option( "wpstg_poll", "no" ) ) {
|
603 |
-
wp_send_json( true );
|
604 |
-
}
|
605 |
-
return wp_send_json();
|
606 |
-
}
|
607 |
-
|
608 |
-
/**
|
609 |
-
* Ajax Hide Rating
|
610 |
-
* @return mixed bool | json
|
611 |
-
*/
|
612 |
-
public function ajaxHideRating() {
|
613 |
-
if( false !== update_option( "wpstg_rating", "no" ) ) {
|
614 |
-
wp_send_json( true );
|
615 |
-
}
|
616 |
-
return wp_send_json();
|
617 |
-
}
|
618 |
-
|
619 |
-
/**
|
620 |
-
* Ajax Hide Beta
|
621 |
-
*/
|
622 |
-
public function ajaxHideBeta() {
|
623 |
-
wp_send_json( update_option( "wpstg_beta", "no" ) );
|
624 |
-
}
|
625 |
-
|
626 |
-
/**
|
627 |
-
* Clone logs
|
628 |
-
*/
|
629 |
-
public function ajaxLogs() {
|
630 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
631 |
-
|
632 |
-
$logs = new Logs();
|
633 |
-
wp_send_json( $logs->start() );
|
634 |
-
}
|
635 |
-
|
636 |
-
/**
|
637 |
-
* Ajax Checks Free Disk Space
|
638 |
-
*/
|
639 |
-
public function ajaxCheckFreeSpace() {
|
640 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
641 |
-
|
642 |
-
$scan = new Scan();
|
643 |
-
return $scan->hasFreeDiskSpace();
|
644 |
-
}
|
645 |
-
|
646 |
-
/**
|
647 |
-
* Ajax Start Push Changes Process
|
648 |
-
* Start with the module Scan
|
649 |
-
*/
|
650 |
-
public function ajaxPushScan() {
|
651 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
652 |
-
|
653 |
-
if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Scan' ) ) {
|
654 |
-
return false;
|
655 |
-
}
|
656 |
-
|
657 |
-
// Scan
|
658 |
-
$scan = new Pro\Modules\Jobs\Scan();
|
659 |
-
|
660 |
-
$scan->start();
|
661 |
-
|
662 |
-
// Get Options
|
663 |
-
$options = $scan->getOptions();
|
664 |
-
|
665 |
-
require_once "{$this->path}Pro/views/scan.php";
|
666 |
-
|
667 |
-
wp_die();
|
668 |
-
}
|
669 |
-
|
670 |
-
/**
|
671 |
-
* Ajax Start Pushing. Needs wp quads pro)
|
672 |
-
*/
|
673 |
-
public function ajaxPushProcessing() {
|
674 |
-
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
675 |
-
|
676 |
-
if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Processing' ) ) {
|
677 |
-
return false;
|
678 |
-
}
|
679 |
-
// Start the process
|
680 |
-
$processing = new Processing();
|
681 |
-
wp_send_json( $processing->start() );
|
682 |
-
}
|
683 |
-
|
684 |
-
/**
|
685 |
-
* License Page
|
686 |
-
*/
|
687 |
-
public function getLicensePage() {
|
688 |
-
|
689 |
-
// Get license data
|
690 |
-
$license = get_option( 'wpstg_license_status' );
|
691 |
-
|
692 |
-
require_once "{$this->path}Pro/views/licensing.php";
|
693 |
-
}
|
694 |
-
|
695 |
-
}
|
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;
|
11 |
+
use WPStaging\Backend\Modules\Jobs\CancelUpdate;
|
12 |
+
use WPStaging\Backend\Modules\Jobs\Cloning;
|
13 |
+
use WPStaging\Backend\Modules\Jobs\Updating;
|
14 |
+
use WPStaging\Backend\Modules\Jobs\Data;
|
15 |
+
use WPStaging\Backend\Modules\Jobs\Database;
|
16 |
+
use WPStaging\Backend\Modules\Jobs\Delete;
|
17 |
+
use WPStaging\Backend\Modules\Jobs\Files;
|
18 |
+
use WPStaging\Backend\Modules\Jobs\Scan;
|
19 |
+
use WPStaging\Backend\Modules\Jobs\Logs;
|
20 |
+
use WPStaging\Backend\Modules\Optimizer;
|
21 |
+
use WPStaging\Backend\Modules\SystemInfo;
|
22 |
+
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
23 |
+
use WPStaging\Backend\Notices\Notices;
|
24 |
+
use WPStaging\DI\InjectionAware;
|
25 |
+
use WPStaging\Backend\Modules\Views\Forms\Settings as FormSettings;
|
26 |
+
use WPStaging\Backend\Activation;
|
27 |
+
use WPStaging\WPStaging;
|
28 |
+
use WPStaging\Backend\Pro\Modules\Jobs\Processing;
|
29 |
+
use WPStaging\Backend\Pro\Licensing;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Class Administrator
|
33 |
+
* @package WPStaging\Backend
|
34 |
+
*/
|
35 |
+
class Administrator extends InjectionAware {
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
private $path;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var string
|
44 |
+
*/
|
45 |
+
private $url;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Initialize class
|
49 |
+
*/
|
50 |
+
public function initialize() {
|
51 |
+
$this->defineHooks();
|
52 |
+
|
53 |
+
// Path to backend
|
54 |
+
$this->path = plugin_dir_path( __FILE__ );
|
55 |
+
|
56 |
+
// URL to public backend folder
|
57 |
+
$this->url = plugin_dir_url( __FILE__ ) . "public/";
|
58 |
+
|
59 |
+
// Load plugins meta data
|
60 |
+
$this->loadMeta();
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Load plugn meta data
|
65 |
+
*/
|
66 |
+
public function loadMeta() {
|
67 |
+
$run = new \WPStaging\Backend\Pluginmeta\Pluginmeta();
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Define Hooks
|
72 |
+
*/
|
73 |
+
private function defineHooks() {
|
74 |
+
// Get loader
|
75 |
+
$loader = $this->di->get( "loader" );
|
76 |
+
|
77 |
+
$Activation = new \WPStaging\Backend\Activation\Activation();
|
78 |
+
|
79 |
+
$Welcome = new Activation\Welcome();
|
80 |
+
|
81 |
+
$loader->addAction( "activated_plugin", $Activation, 'deactivate_other_instances' );
|
82 |
+
$loader->addAction( "admin_menu", $this, "addMenu", 10 );
|
83 |
+
$loader->addAction( "admin_init", $this, "setOptionFormElements" );
|
84 |
+
$loader->addAction( "admin_init", $this, "upgrade" );
|
85 |
+
$loader->addAction( "admin_post_wpstg_download_sysinfo", $this, "systemInfoDownload" );
|
86 |
+
$loader->addAction( "admin_post_wpstg_export", $this, "export" );
|
87 |
+
$loader->addAction( "admin_post_wpstg_import_settings", $this, "import" );
|
88 |
+
$loader->addAction( "admin_notices", $this, "messages" );
|
89 |
+
|
90 |
+
// Ajax Requests
|
91 |
+
$loader->addAction( "wp_ajax_wpstg_overview", $this, "ajaxOverview" );
|
92 |
+
$loader->addAction( "wp_ajax_wpstg_scanning", $this, "ajaxScan" );
|
93 |
+
$loader->addAction( "wp_ajax_wpstg_check_clone", $this, "ajaxcheckCloneName" );
|
94 |
+
//$loader->addAction( "wp_ajax_wpstg_update_struc", $this, "ajaxStartUpdate" );
|
95 |
+
$loader->addAction( "wp_ajax_wpstg_update", $this, "ajaxUpdateProcess" );
|
96 |
+
$loader->addAction( "wp_ajax_wpstg_cloning", $this, "ajaxStartClone" );
|
97 |
+
$loader->addAction( "wp_ajax_wpstg_clone_database", $this, "ajaxCloneDatabase" );
|
98 |
+
$loader->addAction( "wp_ajax_wpstg_clone_prepare_directories", $this, "ajaxPrepareDirectories" );
|
99 |
+
$loader->addAction( "wp_ajax_wpstg_clone_files", $this, "ajaxCopyFiles" );
|
100 |
+
$loader->addAction( "wp_ajax_wpstg_clone_replace_data", $this, "ajaxReplaceData" );
|
101 |
+
$loader->addAction( "wp_ajax_wpstg_clone_finish", $this, "ajaxFinish" );
|
102 |
+
$loader->addAction( "wp_ajax_wpstg_confirm_delete_clone", $this, "ajaxDeleteConfirmation" );
|
103 |
+
$loader->addAction( "wp_ajax_wpstg_delete_clone", $this, "ajaxDeleteClone" );
|
104 |
+
$loader->addAction( "wp_ajax_wpstg_cancel_clone", $this, "ajaxCancelClone" );
|
105 |
+
$loader->addAction( "wp_ajax_wpstg_cancel_update", $this, "ajaxCancelUpdate" );
|
106 |
+
$loader->addAction( "wp_ajax_wpstg_hide_poll", $this, "ajaxHidePoll" );
|
107 |
+
$loader->addAction( "wp_ajax_wpstg_hide_rating", $this, "ajaxHideRating" );
|
108 |
+
$loader->addAction( "wp_ajax_wpstg_hide_beta", $this, "ajaxHideBeta" );
|
109 |
+
$loader->addAction( "wp_ajax_wpstg_logs", $this, "ajaxLogs" );
|
110 |
+
$loader->addAction( "wp_ajax_wpstg_check_disk_space", $this, "ajaxCheckFreeSpace" );
|
111 |
+
|
112 |
+
// Ajax hooks pro Version
|
113 |
+
$loader->addAction( "wp_ajax_wpstg_scan", $this, "ajaxPushScan" );
|
114 |
+
$loader->addAction( "wp_ajax_wpstg_push_processing", $this, "ajaxPushProcessing" );
|
115 |
+
//$loader->addAction( "wp_ajax_wpstg_copy_database", $this, "ajaxCopyDatabase" );
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Register options form elements
|
120 |
+
*/
|
121 |
+
public function setOptionFormElements() {
|
122 |
+
register_setting( "wpstg_settings", "wpstg_settings", array($this, "sanitizeOptions") );
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Upgrade routine
|
127 |
+
*/
|
128 |
+
public function upgrade() {
|
129 |
+
$upgrade = new Upgrade\Upgrade();
|
130 |
+
$upgrade->doUpgrade();
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Sanitize options data and delete the cache
|
135 |
+
* @param array $data
|
136 |
+
* @return array
|
137 |
+
*/
|
138 |
+
public function sanitizeOptions( $data = array() ) {
|
139 |
+
$sanitized = $this->sanitizeData( $data );
|
140 |
+
|
141 |
+
add_settings_error( "wpstg-notices", '', __( "Settings updated.", "wpstg" ), "updated" );
|
142 |
+
|
143 |
+
// Return sanitized data
|
144 |
+
//return $sanitized;
|
145 |
+
return apply_filters( "wpstg-settings", $sanitized, $data );
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @param array $data
|
150 |
+
* @return array
|
151 |
+
*/
|
152 |
+
private function sanitizeData( $data = array() ) {
|
153 |
+
$sanitized = array();
|
154 |
+
|
155 |
+
foreach ( $data as $key => $value ) {
|
156 |
+
$sanitized[$key] = (is_array( $value )) ? $this->sanitizeData( $value ) : htmlspecialchars( $value );
|
157 |
+
}
|
158 |
+
|
159 |
+
return $sanitized;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Add Admin Menu(s)
|
164 |
+
*/
|
165 |
+
public function addMenu() {
|
166 |
+
|
167 |
+
$logo = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGw9Im5vbmUiPgo8Zz48Zz48cGF0aCBzdHlsZT0iZmlsbDojZmZmIiAgZD0iTTEzNy42LDU2MS4zSDEzLjhIMTB2MzA2LjNsOTAuNy04My40QzE4OS42LDkwOC43LDMzNS4zLDk5MCw1MDAsOTkwYzI0OS45LDAsNDU2LjEtMTg3LjEsNDg2LjItNDI4LjhIODYyLjRDODMzLjMsNzM1LjEsNjgyLjEsODY3LjUsNTAwLDg2Ny41Yy0xMjksMC0yNDIuNS02Ni41LTMwOC4xLTE2Ny4ybDE1MS4zLTEzOS4xSDEzNy42eiIvPjxwYXRoIHN0eWxlPSJmaWxsOiNmZmYiICBkPSJNNTAwLDEwQzI1MC4xLDEwLDQzLjksMTk3LjEsMTMuOCw0MzguOGgxMjMuOEMxNjYuNywyNjQuOSwzMTcuOSwxMzIuNSw1MDAsMTMyLjVjMTMyLjksMCwyNDkuMyw3MC41LDMxMy44LDE3Ni4yTDY4My44LDQzOC44aDEyMi41aDU2LjJoMTIzLjhoMy44VjEzMi41bC04Ny43LDg3LjdDODEzLjgsOTMuMSw2NjYuNiwxMCw1MDAsMTB6Ii8+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvZz4KPC9zdmc+';
|
168 |
+
|
169 |
+
// Main WP Staging Menu
|
170 |
+
add_menu_page(
|
171 |
+
"WP-Staging", __( "WP Staging", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage"), $logo
|
172 |
+
);
|
173 |
+
|
174 |
+
// Page: Clone
|
175 |
+
add_submenu_page(
|
176 |
+
"wpstg_clone", __( "WP Staging Jobs", "wpstg" ), __( "Start", "wpstg" ), "manage_options", "wpstg_clone", array($this, "getClonePage")
|
177 |
+
);
|
178 |
+
|
179 |
+
// Page: Settings
|
180 |
+
add_submenu_page(
|
181 |
+
"wpstg_clone", __( "WP Staging Settings", "wpstg" ), __( "Settings", "wpstg" ), "manage_options", "wpstg-settings", array($this, "getSettingsPage")
|
182 |
+
);
|
183 |
+
|
184 |
+
// Page: Tools
|
185 |
+
add_submenu_page(
|
186 |
+
"wpstg_clone", __( "WP Staging Tools", "wpstg" ), __( "Tools", "wpstg" ), "manage_options", "wpstg-tools", array($this, "getToolsPage")
|
187 |
+
);
|
188 |
+
// Page: Tools
|
189 |
+
add_submenu_page(
|
190 |
+
"wpstg_clone", __( "WP Staging Welcome", "wpstg" ), __( "Get WP Staging Pro", "wpstg" ), "manage_options", "wpstg-welcome", array($this, "getWelcomePage")
|
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 |
+
* Welcome Page
|
232 |
+
*/
|
233 |
+
public function getWelcomePage() {
|
234 |
+
require_once "{$this->path}views/welcome/welcome.php";
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Tools Page
|
239 |
+
*/
|
240 |
+
public function getToolsPage() {
|
241 |
+
// Tabs
|
242 |
+
$tabs = new Tabs( array(
|
243 |
+
"import_export" => __( "Import/Export", "wpstg" ),
|
244 |
+
"system_info" => __( "System Info", "wpstg" )
|
245 |
+
) );
|
246 |
+
|
247 |
+
$this->di->set( "tabs", $tabs );
|
248 |
+
|
249 |
+
$this->di->set( "systemInfo", new SystemInfo( $this->di ) );
|
250 |
+
|
251 |
+
require_once "{$this->path}views/tools/index.php";
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* System Information Download
|
256 |
+
*/
|
257 |
+
public function systemInfoDownload() {
|
258 |
+
if( !current_user_can( "update_plugins" ) ) {
|
259 |
+
return;
|
260 |
+
}
|
261 |
+
|
262 |
+
nocache_headers();
|
263 |
+
header( "Content-Type: text/plain" );
|
264 |
+
header( "Content-Disposition: attachment; filename='wpstg-system-info.txt'" );
|
265 |
+
echo wp_strip_all_tags( new SystemInfo( $this->di ) );
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Import JSON settings file
|
270 |
+
*/
|
271 |
+
public function import() {
|
272 |
+
if( empty( $_POST["wpstg_import_nonce"] ) ) {
|
273 |
+
return;
|
274 |
+
}
|
275 |
+
|
276 |
+
if( !wp_verify_nonce( $_POST["wpstg_import_nonce"], "wpstg_import_nonce" ) ) {
|
277 |
+
return;
|
278 |
+
}
|
279 |
+
|
280 |
+
if( !current_user_can( "update_plugins" ) ) {
|
281 |
+
return;
|
282 |
+
}
|
283 |
+
|
284 |
+
$fileExtension = explode( '.', $_FILES["import_file"]["name"] );
|
285 |
+
$fileExtension = end( $fileExtension );
|
286 |
+
if( "json" !== $fileExtension ) {
|
287 |
+
wp_die( "Please upload a valid .json file", "wpstg" );
|
288 |
+
}
|
289 |
+
|
290 |
+
|
291 |
+
$importFile = $_FILES["import_file"]["tmp_name"];
|
292 |
+
|
293 |
+
if( empty( $importFile ) ) {
|
294 |
+
wp_die( __( "Please upload a file to import", "wpstg" ) );
|
295 |
+
}
|
296 |
+
|
297 |
+
update_option( "wpstg_settings", json_decode( file_get_contents( $importFile, true ) ) );
|
298 |
+
|
299 |
+
wp_safe_redirect( admin_url( "admin.php?page=wpstg-tools&wpstg-message=settings-imported" ) );
|
300 |
+
|
301 |
+
return;
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Export settings to JSON file
|
306 |
+
*/
|
307 |
+
public function export() {
|
308 |
+
if( empty( $_POST["wpstg_export_nonce"] ) ) {
|
309 |
+
return;
|
310 |
+
}
|
311 |
+
|
312 |
+
if( !wp_verify_nonce( $_POST["wpstg_export_nonce"], "wpstg_export_nonce" ) ) {
|
313 |
+
return;
|
314 |
+
}
|
315 |
+
|
316 |
+
if( !current_user_can( "manage_options" ) ) {
|
317 |
+
return;
|
318 |
+
}
|
319 |
+
|
320 |
+
$settings = get_option( "wpstg_settings", array() );
|
321 |
+
|
322 |
+
ignore_user_abort( true );
|
323 |
+
|
324 |
+
if( !in_array( "set_time_limit", explode( ',', ini_get( "disable_functions" ) ) ) && !@ini_get( "safe_mode" ) ) {
|
325 |
+
set_time_limit( 0 );
|
326 |
+
}
|
327 |
+
|
328 |
+
$fileName = apply_filters( "wpstg_settings_export_filename", "wpstg-settings-export-" . date( "m-d-Y" ) ) . ".json";
|
329 |
+
|
330 |
+
nocache_headers();
|
331 |
+
header( "Content-Type: application/json; charset=utf-8" );
|
332 |
+
header( "Content-Disposition: attachment; filename={$fileName}" );
|
333 |
+
header( "Expires: 0" );
|
334 |
+
|
335 |
+
echo json_encode( $settings );
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Render a view file
|
340 |
+
* @param string $file
|
341 |
+
* @param array $vars
|
342 |
+
* @return string
|
343 |
+
*/
|
344 |
+
public function render( $file, $vars = array() ) {
|
345 |
+
$fullPath = $this->path . "views" . DIRECTORY_SEPARATOR;
|
346 |
+
$fullPath = str_replace( array('/', "\\"), DIRECTORY_SEPARATOR, $fullPath . $file . ".php" );
|
347 |
+
|
348 |
+
if( !file_exists( $fullPath ) || !is_readable( $fullPath ) ) {
|
349 |
+
return "Can't render : {$fullPath} either file doesn't exist or can't read it";
|
350 |
+
}
|
351 |
+
|
352 |
+
$contents = @file_get_contents( $fullPath );
|
353 |
+
|
354 |
+
// Variables are set
|
355 |
+
if( count( $vars ) > 0 ) {
|
356 |
+
$vars = array_combine(
|
357 |
+
array_map( function ($key) {
|
358 |
+
return "{{" . $key . "}}";
|
359 |
+
}, array_keys( $vars )
|
360 |
+
), $vars
|
361 |
+
);
|
362 |
+
|
363 |
+
$contents = str_replace( array_keys( $vars ), array_values( $vars ), $contents );
|
364 |
+
}
|
365 |
+
|
366 |
+
return $contents;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Ajax Overview
|
371 |
+
*/
|
372 |
+
public function ajaxOverview() {
|
373 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
374 |
+
|
375 |
+
// Existing clones
|
376 |
+
$availableClones = get_option( "wpstg_existing_clones_beta", array() );
|
377 |
+
|
378 |
+
// Get license data
|
379 |
+
$license = get_option( 'wpstg_license_status' );
|
380 |
+
|
381 |
+
|
382 |
+
if( \WPStaging\WPStaging::getSlug() === 'wp-staging-pro' ) {
|
383 |
+
require_once "{$this->path}Pro/views/single-overview-pro.php";
|
384 |
+
} else {
|
385 |
+
require_once "{$this->path}views/clone/ajax/single-overview.php";
|
386 |
+
}
|
387 |
+
|
388 |
+
wp_die();
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Ajax Scan
|
393 |
+
*/
|
394 |
+
public function ajaxScan() {
|
395 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
396 |
+
|
397 |
+
// Scan
|
398 |
+
$scan = new Scan();
|
399 |
+
$scan->start();
|
400 |
+
|
401 |
+
// Get Options
|
402 |
+
$options = $scan->getOptions();
|
403 |
+
|
404 |
+
require_once "{$this->path}views/clone/ajax/scan.php";
|
405 |
+
|
406 |
+
wp_die();
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Ajax Check Clone Name
|
411 |
+
*/
|
412 |
+
public function ajaxCheckCloneName() {
|
413 |
+
$cloneName = sanitize_key( $_POST["cloneID"] );
|
414 |
+
$cloneNameLength = strlen( $cloneName );
|
415 |
+
$clones = get_option( "wpstg_existing_clones_beta", array() );
|
416 |
+
|
417 |
+
// Check clone name length
|
418 |
+
if( $cloneNameLength < 1 || $cloneNameLength > 16 ) {
|
419 |
+
echo wp_send_json( array(
|
420 |
+
"status" => "failed",
|
421 |
+
"message" => "Clone name must be between 1 - 16 characters"
|
422 |
+
) );
|
423 |
+
} elseif( array_key_exists( $cloneName, $clones ) ) {
|
424 |
+
echo wp_send_json( array(
|
425 |
+
"status" => "failed",
|
426 |
+
"message" => "Clone name is already in use, please choose an another clone name"
|
427 |
+
) );
|
428 |
+
}
|
429 |
+
|
430 |
+
echo wp_send_json( array("status" => "success") );
|
431 |
+
}
|
432 |
+
|
433 |
+
|
434 |
+
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Ajax Start Updating Clone (Basically just layout and saving data)
|
438 |
+
*/
|
439 |
+
// public function ajaxStartUpdate() {
|
440 |
+
// check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
441 |
+
//
|
442 |
+
// $cloning = new Updating();
|
443 |
+
//
|
444 |
+
// if( !$cloning->save() ) {
|
445 |
+
// wp_die('can not save clone data');
|
446 |
+
// }
|
447 |
+
//
|
448 |
+
// require_once "{$this->path}views/clone/ajax/update.php";
|
449 |
+
//
|
450 |
+
// wp_die();
|
451 |
+
// }
|
452 |
+
/**
|
453 |
+
* Ajax Start Updating Clone (Basically just layout and saving data)
|
454 |
+
*/
|
455 |
+
public function ajaxUpdateProcess() {
|
456 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
457 |
+
|
458 |
+
$cloning = new Updating();
|
459 |
+
|
460 |
+
if( !$cloning->save() ) {
|
461 |
+
wp_die('can not save clone data');
|
462 |
+
}
|
463 |
+
|
464 |
+
require_once "{$this->path}views/clone/ajax/update.php";
|
465 |
+
|
466 |
+
wp_die();
|
467 |
+
|
468 |
+
//wp_send_json( $cloning->start() );
|
469 |
+
}
|
470 |
+
/**
|
471 |
+
* Ajax Start Clone (Basically just layout and saving data)
|
472 |
+
*/
|
473 |
+
public function ajaxStartClone() {
|
474 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
475 |
+
|
476 |
+
$cloning = new Cloning();
|
477 |
+
|
478 |
+
if( !$cloning->save() ) {
|
479 |
+
wp_die('can not save clone data');
|
480 |
+
}
|
481 |
+
|
482 |
+
require_once "{$this->path}views/clone/ajax/start.php";
|
483 |
+
|
484 |
+
wp_die();
|
485 |
+
}
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Ajax Clone Database
|
489 |
+
*/
|
490 |
+
public function ajaxCloneDatabase() {
|
491 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
492 |
+
|
493 |
+
$cloning = new Cloning();
|
494 |
+
|
495 |
+
wp_send_json( $cloning->start() );
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Ajax Prepare Directories (get listing of files)
|
500 |
+
*/
|
501 |
+
public function ajaxPrepareDirectories() {
|
502 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
503 |
+
|
504 |
+
$cloning = new Cloning();
|
505 |
+
|
506 |
+
wp_send_json( $cloning->start() );
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Ajax Clone Files
|
511 |
+
*/
|
512 |
+
public function ajaxCopyFiles() {
|
513 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
514 |
+
|
515 |
+
$cloning = new Cloning();
|
516 |
+
|
517 |
+
wp_send_json( $cloning->start() );
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Ajax Replace Data
|
522 |
+
*/
|
523 |
+
public function ajaxReplaceData() {
|
524 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
525 |
+
|
526 |
+
$cloning = new Cloning();
|
527 |
+
|
528 |
+
wp_send_json( $cloning->start() );
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Ajax Finish
|
533 |
+
*/
|
534 |
+
public function ajaxFinish() {
|
535 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
536 |
+
|
537 |
+
$cloning = new Cloning();
|
538 |
+
|
539 |
+
wp_send_json( $cloning->start() );
|
540 |
+
}
|
541 |
+
|
542 |
+
/**
|
543 |
+
* Ajax Delete Confirmation
|
544 |
+
*/
|
545 |
+
public function ajaxDeleteConfirmation() {
|
546 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
547 |
+
|
548 |
+
$delete = new Delete();
|
549 |
+
$delete->setData();
|
550 |
+
|
551 |
+
$clone = $delete->getClone();
|
552 |
+
|
553 |
+
require_once "{$this->path}views/clone/ajax/delete-confirmation.php";
|
554 |
+
|
555 |
+
wp_die();
|
556 |
+
}
|
557 |
+
|
558 |
+
/**
|
559 |
+
* Delete clone
|
560 |
+
*/
|
561 |
+
public function ajaxDeleteClone() {
|
562 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
563 |
+
|
564 |
+
$delete = new Delete();
|
565 |
+
wp_send_json( $delete->start() );
|
566 |
+
}
|
567 |
+
|
568 |
+
/**
|
569 |
+
* Delete clone
|
570 |
+
*/
|
571 |
+
public function ajaxCancelClone() {
|
572 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
573 |
+
|
574 |
+
$cancel = new Cancel();
|
575 |
+
wp_send_json( $cancel->start() );
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Cancel updating process / Do not delete clone!
|
580 |
+
*/
|
581 |
+
public function ajaxCancelUpdate() {
|
582 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
583 |
+
|
584 |
+
$cancel = new CancelUpdate();
|
585 |
+
wp_send_json( $cancel->start() );
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* Admin Messages
|
590 |
+
*/
|
591 |
+
public function messages() {
|
592 |
+
$notice = new Notices( $this->path, $this->url );
|
593 |
+
|
594 |
+
$run = $notice->messages();
|
595 |
+
}
|
596 |
+
|
597 |
+
/**
|
598 |
+
* Ajax Hide Poll
|
599 |
+
* @return mixed boolean | json
|
600 |
+
*/
|
601 |
+
public function ajaxHidePoll() {
|
602 |
+
if( false !== update_option( "wpstg_poll", "no" ) ) {
|
603 |
+
wp_send_json( true );
|
604 |
+
}
|
605 |
+
return wp_send_json();
|
606 |
+
}
|
607 |
+
|
608 |
+
/**
|
609 |
+
* Ajax Hide Rating
|
610 |
+
* @return mixed bool | json
|
611 |
+
*/
|
612 |
+
public function ajaxHideRating() {
|
613 |
+
if( false !== update_option( "wpstg_rating", "no" ) ) {
|
614 |
+
wp_send_json( true );
|
615 |
+
}
|
616 |
+
return wp_send_json();
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* Ajax Hide Beta
|
621 |
+
*/
|
622 |
+
public function ajaxHideBeta() {
|
623 |
+
wp_send_json( update_option( "wpstg_beta", "no" ) );
|
624 |
+
}
|
625 |
+
|
626 |
+
/**
|
627 |
+
* Clone logs
|
628 |
+
*/
|
629 |
+
public function ajaxLogs() {
|
630 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
631 |
+
|
632 |
+
$logs = new Logs();
|
633 |
+
wp_send_json( $logs->start() );
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Ajax Checks Free Disk Space
|
638 |
+
*/
|
639 |
+
public function ajaxCheckFreeSpace() {
|
640 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
641 |
+
|
642 |
+
$scan = new Scan();
|
643 |
+
return $scan->hasFreeDiskSpace();
|
644 |
+
}
|
645 |
+
|
646 |
+
/**
|
647 |
+
* Ajax Start Push Changes Process
|
648 |
+
* Start with the module Scan
|
649 |
+
*/
|
650 |
+
public function ajaxPushScan() {
|
651 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
652 |
+
|
653 |
+
if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Scan' ) ) {
|
654 |
+
return false;
|
655 |
+
}
|
656 |
+
|
657 |
+
// Scan
|
658 |
+
$scan = new Pro\Modules\Jobs\Scan();
|
659 |
+
|
660 |
+
$scan->start();
|
661 |
+
|
662 |
+
// Get Options
|
663 |
+
$options = $scan->getOptions();
|
664 |
+
|
665 |
+
require_once "{$this->path}Pro/views/scan.php";
|
666 |
+
|
667 |
+
wp_die();
|
668 |
+
}
|
669 |
+
|
670 |
+
/**
|
671 |
+
* Ajax Start Pushing. Needs wp quads pro)
|
672 |
+
*/
|
673 |
+
public function ajaxPushProcessing() {
|
674 |
+
check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
|
675 |
+
|
676 |
+
if( !class_exists( 'WPStaging\Backend\Pro\Modules\Jobs\Processing' ) ) {
|
677 |
+
return false;
|
678 |
+
}
|
679 |
+
// Start the process
|
680 |
+
$processing = new Processing();
|
681 |
+
wp_send_json( $processing->start() );
|
682 |
+
}
|
683 |
+
|
684 |
+
/**
|
685 |
+
* License Page
|
686 |
+
*/
|
687 |
+
public function getLicensePage() {
|
688 |
+
|
689 |
+
// Get license data
|
690 |
+
$license = get_option( 'wpstg_license_status' );
|
691 |
+
|
692 |
+
require_once "{$this->path}Pro/views/licensing.php";
|
693 |
+
}
|
694 |
+
|
695 |
+
}
|
apps/Backend/Modules/Jobs/Cancel.php
CHANGED
@@ -1,74 +1,74 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Cancel Processing
|
7 |
-
* @package WPStaging\Backend\Modules\Jobs
|
8 |
-
*/
|
9 |
-
class Cancel extends Job {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Start Module
|
13 |
-
* @return bool
|
14 |
-
*/
|
15 |
-
public function start() {
|
16 |
-
$cloneData = $this->createCloneData();
|
17 |
-
|
18 |
-
if (empty($cloneData)) {
|
19 |
-
return true;
|
20 |
-
}
|
21 |
-
|
22 |
-
|
23 |
-
$delete = new Delete();
|
24 |
-
return $delete->start($cloneData);
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @return array
|
29 |
-
*/
|
30 |
-
protected function createCloneData() {
|
31 |
-
$clone = array();
|
32 |
-
|
33 |
-
if (!$this->check()) {
|
34 |
-
return $clone;
|
35 |
-
}
|
36 |
-
|
37 |
-
$clone["name"] = $this->options->clone;
|
38 |
-
$clone["number"] = $this->options->cloneNumber;
|
39 |
-
$clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
|
40 |
-
$clone["prefix"] = ABSPATH . $this->options->prefix;
|
41 |
-
|
42 |
-
return $clone;
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @return bool
|
47 |
-
*/
|
48 |
-
public function check() {
|
49 |
-
return (
|
50 |
-
isset($this->options) &&
|
51 |
-
isset($this->options->clone) &&
|
52 |
-
isset($this->options->cloneNumber) &&
|
53 |
-
isset($this->options->cloneDirectoryName) &&
|
54 |
-
isset($_POST["clone"]) &&
|
55 |
-
$_POST["clone"] === $this->options->clone
|
56 |
-
);
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Get json response
|
61 |
-
* return json
|
62 |
-
*/
|
63 |
-
private function returnFinish($message = '') {
|
64 |
-
|
65 |
-
wp_die(json_encode(array(
|
66 |
-
'job' => 'delete',
|
67 |
-
'status' => true,
|
68 |
-
'message' => $message,
|
69 |
-
'error' => false,
|
70 |
-
'delete' => 'finished'
|
71 |
-
)));
|
72 |
-
}
|
73 |
-
|
74 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Cancel Processing
|
7 |
+
* @package WPStaging\Backend\Modules\Jobs
|
8 |
+
*/
|
9 |
+
class Cancel extends Job {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Start Module
|
13 |
+
* @return bool
|
14 |
+
*/
|
15 |
+
public function start() {
|
16 |
+
$cloneData = $this->createCloneData();
|
17 |
+
|
18 |
+
if (empty($cloneData)) {
|
19 |
+
return true;
|
20 |
+
}
|
21 |
+
|
22 |
+
|
23 |
+
$delete = new Delete();
|
24 |
+
return $delete->start($cloneData);
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @return array
|
29 |
+
*/
|
30 |
+
protected function createCloneData() {
|
31 |
+
$clone = array();
|
32 |
+
|
33 |
+
if (!$this->check()) {
|
34 |
+
return $clone;
|
35 |
+
}
|
36 |
+
|
37 |
+
$clone["name"] = $this->options->clone;
|
38 |
+
$clone["number"] = $this->options->cloneNumber;
|
39 |
+
$clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
|
40 |
+
$clone["prefix"] = ABSPATH . $this->options->prefix;
|
41 |
+
|
42 |
+
return $clone;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return bool
|
47 |
+
*/
|
48 |
+
public function check() {
|
49 |
+
return (
|
50 |
+
isset($this->options) &&
|
51 |
+
isset($this->options->clone) &&
|
52 |
+
isset($this->options->cloneNumber) &&
|
53 |
+
isset($this->options->cloneDirectoryName) &&
|
54 |
+
isset($_POST["clone"]) &&
|
55 |
+
$_POST["clone"] === $this->options->clone
|
56 |
+
);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Get json response
|
61 |
+
* return json
|
62 |
+
*/
|
63 |
+
private function returnFinish($message = '') {
|
64 |
+
|
65 |
+
wp_die(json_encode(array(
|
66 |
+
'job' => 'delete',
|
67 |
+
'status' => true,
|
68 |
+
'message' => $message,
|
69 |
+
'error' => false,
|
70 |
+
'delete' => 'finished'
|
71 |
+
)));
|
72 |
+
}
|
73 |
+
|
74 |
+
}
|
apps/Backend/Modules/Jobs/CancelUpdate.php
CHANGED
@@ -1,90 +1,90 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Cancel Update Processing
|
7 |
-
* @package WPStaging\Backend\Modules\Jobs
|
8 |
-
*/
|
9 |
-
class CancelUpdate extends Job {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Start Module
|
13 |
-
* @return bool
|
14 |
-
*/
|
15 |
-
public function start() {
|
16 |
-
$cloneData = $this->createCloneData();
|
17 |
-
|
18 |
-
if (empty($cloneData)) {
|
19 |
-
return true;
|
20 |
-
}
|
21 |
-
// Delete Cache Files
|
22 |
-
$this->deleteCacheFiles();
|
23 |
-
|
24 |
-
$this->returnFinish();
|
25 |
-
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @return array
|
30 |
-
*/
|
31 |
-
protected function createCloneData() {
|
32 |
-
$clone = array();
|
33 |
-
|
34 |
-
if (!$this->check()) {
|
35 |
-
return $clone;
|
36 |
-
}
|
37 |
-
|
38 |
-
$clone["name"] = $this->options->clone;
|
39 |
-
$clone["number"] = $this->options->cloneNumber;
|
40 |
-
$clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
|
41 |
-
$clone["prefix"] = ABSPATH . $this->options->prefix;
|
42 |
-
|
43 |
-
return $clone;
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @return bool
|
48 |
-
*/
|
49 |
-
public function check() {
|
50 |
-
return (
|
51 |
-
isset($this->options) &&
|
52 |
-
isset($this->options->clone) &&
|
53 |
-
isset($this->options->cloneNumber) &&
|
54 |
-
isset($this->options->cloneDirectoryName) &&
|
55 |
-
isset($_POST["clone"]) &&
|
56 |
-
$_POST["clone"] === $this->options->clone
|
57 |
-
);
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Get json response
|
62 |
-
* return json
|
63 |
-
*/
|
64 |
-
private function returnFinish($message = '') {
|
65 |
-
|
66 |
-
wp_die(json_encode(array(
|
67 |
-
'job' => 'delete',
|
68 |
-
'status' => true,
|
69 |
-
'message' => $message,
|
70 |
-
'error' => false,
|
71 |
-
'delete' => 'finished'
|
72 |
-
)));
|
73 |
-
}
|
74 |
-
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Delete Cache Files
|
78 |
-
*/
|
79 |
-
protected function deleteCacheFiles()
|
80 |
-
{
|
81 |
-
$this->log("Cancel Updating: Deleting clone job's cache files...");
|
82 |
-
|
83 |
-
// Clean cache files
|
84 |
-
$this->cache->delete("clone_options");
|
85 |
-
$this->cache->delete("files_to_copy");
|
86 |
-
|
87 |
-
$this->log("Updating process canceled");
|
88 |
-
}
|
89 |
-
|
90 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Cancel Update Processing
|
7 |
+
* @package WPStaging\Backend\Modules\Jobs
|
8 |
+
*/
|
9 |
+
class CancelUpdate extends Job {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Start Module
|
13 |
+
* @return bool
|
14 |
+
*/
|
15 |
+
public function start() {
|
16 |
+
$cloneData = $this->createCloneData();
|
17 |
+
|
18 |
+
if (empty($cloneData)) {
|
19 |
+
return true;
|
20 |
+
}
|
21 |
+
// Delete Cache Files
|
22 |
+
$this->deleteCacheFiles();
|
23 |
+
|
24 |
+
$this->returnFinish();
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @return array
|
30 |
+
*/
|
31 |
+
protected function createCloneData() {
|
32 |
+
$clone = array();
|
33 |
+
|
34 |
+
if (!$this->check()) {
|
35 |
+
return $clone;
|
36 |
+
}
|
37 |
+
|
38 |
+
$clone["name"] = $this->options->clone;
|
39 |
+
$clone["number"] = $this->options->cloneNumber;
|
40 |
+
$clone["path"] = ABSPATH . $this->options->cloneDirectoryName;
|
41 |
+
$clone["prefix"] = ABSPATH . $this->options->prefix;
|
42 |
+
|
43 |
+
return $clone;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
+
public function check() {
|
50 |
+
return (
|
51 |
+
isset($this->options) &&
|
52 |
+
isset($this->options->clone) &&
|
53 |
+
isset($this->options->cloneNumber) &&
|
54 |
+
isset($this->options->cloneDirectoryName) &&
|
55 |
+
isset($_POST["clone"]) &&
|
56 |
+
$_POST["clone"] === $this->options->clone
|
57 |
+
);
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Get json response
|
62 |
+
* return json
|
63 |
+
*/
|
64 |
+
private function returnFinish($message = '') {
|
65 |
+
|
66 |
+
wp_die(json_encode(array(
|
67 |
+
'job' => 'delete',
|
68 |
+
'status' => true,
|
69 |
+
'message' => $message,
|
70 |
+
'error' => false,
|
71 |
+
'delete' => 'finished'
|
72 |
+
)));
|
73 |
+
}
|
74 |
+
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Delete Cache Files
|
78 |
+
*/
|
79 |
+
protected function deleteCacheFiles()
|
80 |
+
{
|
81 |
+
$this->log("Cancel Updating: Deleting clone job's cache files...");
|
82 |
+
|
83 |
+
// Clean cache files
|
84 |
+
$this->cache->delete("clone_options");
|
85 |
+
$this->cache->delete("files_to_copy");
|
86 |
+
|
87 |
+
$this->log("Updating process canceled");
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
apps/Backend/Modules/Jobs/Cloning.php
CHANGED
@@ -1,250 +1,250 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
-
use WPStaging\WPStaging;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Cloning
|
9 |
-
* @package WPStaging\Backend\Modules\Jobs
|
10 |
-
*/
|
11 |
-
class Cloning extends Job
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* Initialize is called in \Job
|
15 |
-
*/
|
16 |
-
public function initialize(){
|
17 |
-
$this->db = WPStaging::getInstance()->get("wpdb");
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Save Chosen Cloning Settings
|
22 |
-
* @return bool
|
23 |
-
*/
|
24 |
-
public function save()
|
25 |
-
{
|
26 |
-
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
27 |
-
{
|
28 |
-
return false;
|
29 |
-
}
|
30 |
-
|
31 |
-
// Generate Options
|
32 |
-
// Clone
|
33 |
-
$this->options->clone = $_POST["cloneID"];
|
34 |
-
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
35 |
-
$this->options->cloneNumber = 1;
|
36 |
-
$this->options->prefix = $this->getStagingPrefix();
|
37 |
-
|
38 |
-
//$this->options->prefix = $this->getStagingPrefix();
|
39 |
-
$this->options->includedDirectories = array();
|
40 |
-
$this->options->excludedDirectories = array();
|
41 |
-
$this->options->extraDirectories = array();
|
42 |
-
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
43 |
-
|
44 |
-
// Job
|
45 |
-
$this->options->job = new \stdClass();
|
46 |
-
|
47 |
-
// Check if clone data already exists and use that one
|
48 |
-
if (isset($this->options->existingClones[$this->options->clone]) )
|
49 |
-
{
|
50 |
-
|
51 |
-
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]->number;
|
52 |
-
|
53 |
-
$this->options->prefix = isset($this->options->existingClones[$this->options->clone]->prefix) ?
|
54 |
-
$this->options->existingClones[$this->options->clone]->prefix :
|
55 |
-
$this->getStagingPrefix();
|
56 |
-
|
57 |
-
} // Clone does not exist but there are other clones in db
|
58 |
-
// Get data and increment it
|
59 |
-
elseif (!empty($this->options->existingClones))
|
60 |
-
{
|
61 |
-
$this->options->cloneNumber = count($this->options->existingClones)+1;
|
62 |
-
$this->options->prefix = $this->getStagingPrefix();
|
63 |
-
}
|
64 |
-
|
65 |
-
// Excluded Tables
|
66 |
-
if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
67 |
-
{
|
68 |
-
$this->options->excludedTables = $_POST["excludedTables"];
|
69 |
-
}
|
70 |
-
|
71 |
-
// Excluded Directories
|
72 |
-
if (isset($_POST["excludedDirectories"]) && is_array($_POST["excludedDirectories"]))
|
73 |
-
{
|
74 |
-
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
75 |
-
}
|
76 |
-
|
77 |
-
// Excluded Directories TOTAL
|
78 |
-
// Do not copy these folders and plugins
|
79 |
-
$excludedDirectories = array(
|
80 |
-
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
|
81 |
-
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
82 |
-
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-super-cache',
|
83 |
-
);
|
84 |
-
|
85 |
-
$this->options->excludedDirectories = array_merge($excludedDirectories, $this->options->excludedDirectories);
|
86 |
-
|
87 |
-
// Included Directories
|
88 |
-
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
89 |
-
{
|
90 |
-
$this->options->includedDirectories = $_POST["includedDirectories"];
|
91 |
-
}
|
92 |
-
|
93 |
-
// Extra Directories
|
94 |
-
if (isset($_POST["extraDirectories"]) && !empty($_POST["extraDirectories"]) )
|
95 |
-
{
|
96 |
-
$this->options->extraDirectories = $_POST["extraDirectories"];
|
97 |
-
}
|
98 |
-
|
99 |
-
// Directories to Copy
|
100 |
-
$this->options->directoriesToCopy = array_merge(
|
101 |
-
$this->options->includedDirectories,
|
102 |
-
$this->options->extraDirectories
|
103 |
-
);
|
104 |
-
|
105 |
-
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
106 |
-
|
107 |
-
// Delete files to copy listing
|
108 |
-
$this->cache->delete("files_to_copy");
|
109 |
-
|
110 |
-
return $this->saveOptions();
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Create a new staging prefix which does not already exists in database
|
115 |
-
*/
|
116 |
-
public function getStagingPrefix(){
|
117 |
-
|
118 |
-
// Find a new prefix that does not already exist in database.
|
119 |
-
// 1000 different possible prefixes should be enough here
|
120 |
-
for($i=0; $i <= 10000; $i++){
|
121 |
-
$this->options->prefix = isset($this->options->existingClones) ?
|
122 |
-
'wpstg' . (count($this->options->existingClones)+$i) . '_' :
|
123 |
-
'wpstg' . $i . '_';
|
124 |
-
|
125 |
-
$sql = "SHOW TABLE STATUS LIKE '{$this->options->prefix}%'";
|
126 |
-
$tables = $this->db->get_results($sql);
|
127 |
-
|
128 |
-
// Prefix does not exists. We can use it
|
129 |
-
if (!$tables){
|
130 |
-
//$this->returnException('new ' . $this->options->prefix);
|
131 |
-
return $this->options->prefix;
|
132 |
-
}
|
133 |
-
}
|
134 |
-
$this->returnException("Fatal Error: Can not create staging prefix. '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com");
|
135 |
-
wp_die("Fatal Error: Can not create staging prefix. Prefix '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com");
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Check if potential new prefix of staging site would be identical with live site.
|
140 |
-
* @return boolean
|
141 |
-
*/
|
142 |
-
private function isPrefixIdentical(){
|
143 |
-
$db = WPStaging::getInstance()->get("wpdb");
|
144 |
-
|
145 |
-
$livePrefix = $db->prefix;
|
146 |
-
$stagingPrefix = $this->options->prefix;
|
147 |
-
|
148 |
-
if ($livePrefix == $stagingPrefix){
|
149 |
-
return true;
|
150 |
-
}
|
151 |
-
return false;
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Start the cloning job
|
156 |
-
*/
|
157 |
-
public function start()
|
158 |
-
{
|
159 |
-
if (null === $this->options->currentJob)
|
160 |
-
{
|
161 |
-
$this->log("Cloning job for {$this->options->clone} finished");
|
162 |
-
return true;
|
163 |
-
}
|
164 |
-
|
165 |
-
$methodName = "job" . ucwords($this->options->currentJob);
|
166 |
-
|
167 |
-
if (!method_exists($this, $methodName))
|
168 |
-
{
|
169 |
-
$this->log("Can't execute job; Job's method {$methodName} is not found");
|
170 |
-
throw new JobNotFoundException($methodName);
|
171 |
-
}
|
172 |
-
|
173 |
-
// Call the job
|
174 |
-
//$this->log("execute job: Job's method {$methodName}");
|
175 |
-
return $this->{$methodName}();
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* @param object $response
|
180 |
-
* @param string $nextJob
|
181 |
-
* @return object
|
182 |
-
*/
|
183 |
-
private function handleJobResponse($response, $nextJob)
|
184 |
-
{
|
185 |
-
// Job is not done
|
186 |
-
if (true !== $response->status)
|
187 |
-
{
|
188 |
-
return $response;
|
189 |
-
}
|
190 |
-
|
191 |
-
$this->options->currentJob = $nextJob;
|
192 |
-
$this->options->currentStep = 0;
|
193 |
-
$this->options->totalSteps = 0;
|
194 |
-
|
195 |
-
// Save options
|
196 |
-
$this->saveOptions();
|
197 |
-
|
198 |
-
return $response;
|
199 |
-
}
|
200 |
-
|
201 |
-
/**
|
202 |
-
* Clone Database
|
203 |
-
* @return object
|
204 |
-
*/
|
205 |
-
public function jobDatabase()
|
206 |
-
{
|
207 |
-
$database = new Database();
|
208 |
-
return $this->handleJobResponse($database->start(), "directories");
|
209 |
-
}
|
210 |
-
|
211 |
-
/**
|
212 |
-
* Get All Files From Selected Directories Recursively Into a File
|
213 |
-
* @return object
|
214 |
-
*/
|
215 |
-
public function jobDirectories()
|
216 |
-
{
|
217 |
-
$directories = new Directories();
|
218 |
-
return $this->handleJobResponse($directories->start(), "files");
|
219 |
-
}
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Copy Files
|
223 |
-
* @return object
|
224 |
-
*/
|
225 |
-
public function jobFiles()
|
226 |
-
{
|
227 |
-
$files = new Files();
|
228 |
-
return $this->handleJobResponse($files->start(), "data");
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Replace Data
|
233 |
-
* @return object
|
234 |
-
*/
|
235 |
-
public function jobData()
|
236 |
-
{
|
237 |
-
$data = new Data();
|
238 |
-
return $this->handleJobResponse($data->start(), "finish");
|
239 |
-
}
|
240 |
-
|
241 |
-
/**
|
242 |
-
* Save Clone Data
|
243 |
-
* @return object
|
244 |
-
*/
|
245 |
-
public function jobFinish()
|
246 |
-
{
|
247 |
-
$finish = new Finish();
|
248 |
-
return $this->handleJobResponse($finish->start(), '');
|
249 |
-
}
|
250 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
+
use WPStaging\WPStaging;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Cloning
|
9 |
+
* @package WPStaging\Backend\Modules\Jobs
|
10 |
+
*/
|
11 |
+
class Cloning extends Job
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Initialize is called in \Job
|
15 |
+
*/
|
16 |
+
public function initialize(){
|
17 |
+
$this->db = WPStaging::getInstance()->get("wpdb");
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Save Chosen Cloning Settings
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
+
public function save()
|
25 |
+
{
|
26 |
+
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
27 |
+
{
|
28 |
+
return false;
|
29 |
+
}
|
30 |
+
|
31 |
+
// Generate Options
|
32 |
+
// Clone
|
33 |
+
$this->options->clone = $_POST["cloneID"];
|
34 |
+
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
35 |
+
$this->options->cloneNumber = 1;
|
36 |
+
$this->options->prefix = $this->getStagingPrefix();
|
37 |
+
|
38 |
+
//$this->options->prefix = $this->getStagingPrefix();
|
39 |
+
$this->options->includedDirectories = array();
|
40 |
+
$this->options->excludedDirectories = array();
|
41 |
+
$this->options->extraDirectories = array();
|
42 |
+
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
43 |
+
|
44 |
+
// Job
|
45 |
+
$this->options->job = new \stdClass();
|
46 |
+
|
47 |
+
// Check if clone data already exists and use that one
|
48 |
+
if (isset($this->options->existingClones[$this->options->clone]) )
|
49 |
+
{
|
50 |
+
|
51 |
+
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]->number;
|
52 |
+
|
53 |
+
$this->options->prefix = isset($this->options->existingClones[$this->options->clone]->prefix) ?
|
54 |
+
$this->options->existingClones[$this->options->clone]->prefix :
|
55 |
+
$this->getStagingPrefix();
|
56 |
+
|
57 |
+
} // Clone does not exist but there are other clones in db
|
58 |
+
// Get data and increment it
|
59 |
+
elseif (!empty($this->options->existingClones))
|
60 |
+
{
|
61 |
+
$this->options->cloneNumber = count($this->options->existingClones)+1;
|
62 |
+
$this->options->prefix = $this->getStagingPrefix();
|
63 |
+
}
|
64 |
+
|
65 |
+
// Excluded Tables
|
66 |
+
if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
67 |
+
{
|
68 |
+
$this->options->excludedTables = $_POST["excludedTables"];
|
69 |
+
}
|
70 |
+
|
71 |
+
// Excluded Directories
|
72 |
+
if (isset($_POST["excludedDirectories"]) && is_array($_POST["excludedDirectories"]))
|
73 |
+
{
|
74 |
+
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
75 |
+
}
|
76 |
+
|
77 |
+
// Excluded Directories TOTAL
|
78 |
+
// Do not copy these folders and plugins
|
79 |
+
$excludedDirectories = array(
|
80 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
|
81 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login',
|
82 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-super-cache',
|
83 |
+
);
|
84 |
+
|
85 |
+
$this->options->excludedDirectories = array_merge($excludedDirectories, $this->options->excludedDirectories);
|
86 |
+
|
87 |
+
// Included Directories
|
88 |
+
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
89 |
+
{
|
90 |
+
$this->options->includedDirectories = $_POST["includedDirectories"];
|
91 |
+
}
|
92 |
+
|
93 |
+
// Extra Directories
|
94 |
+
if (isset($_POST["extraDirectories"]) && !empty($_POST["extraDirectories"]) )
|
95 |
+
{
|
96 |
+
$this->options->extraDirectories = $_POST["extraDirectories"];
|
97 |
+
}
|
98 |
+
|
99 |
+
// Directories to Copy
|
100 |
+
$this->options->directoriesToCopy = array_merge(
|
101 |
+
$this->options->includedDirectories,
|
102 |
+
$this->options->extraDirectories
|
103 |
+
);
|
104 |
+
|
105 |
+
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
106 |
+
|
107 |
+
// Delete files to copy listing
|
108 |
+
$this->cache->delete("files_to_copy");
|
109 |
+
|
110 |
+
return $this->saveOptions();
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Create a new staging prefix which does not already exists in database
|
115 |
+
*/
|
116 |
+
public function getStagingPrefix(){
|
117 |
+
|
118 |
+
// Find a new prefix that does not already exist in database.
|
119 |
+
// 1000 different possible prefixes should be enough here
|
120 |
+
for($i=0; $i <= 10000; $i++){
|
121 |
+
$this->options->prefix = isset($this->options->existingClones) ?
|
122 |
+
'wpstg' . (count($this->options->existingClones)+$i) . '_' :
|
123 |
+
'wpstg' . $i . '_';
|
124 |
+
|
125 |
+
$sql = "SHOW TABLE STATUS LIKE '{$this->options->prefix}%'";
|
126 |
+
$tables = $this->db->get_results($sql);
|
127 |
+
|
128 |
+
// Prefix does not exists. We can use it
|
129 |
+
if (!$tables){
|
130 |
+
//$this->returnException('new ' . $this->options->prefix);
|
131 |
+
return $this->options->prefix;
|
132 |
+
}
|
133 |
+
}
|
134 |
+
$this->returnException("Fatal Error: Can not create staging prefix. '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com");
|
135 |
+
wp_die("Fatal Error: Can not create staging prefix. Prefix '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com");
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Check if potential new prefix of staging site would be identical with live site.
|
140 |
+
* @return boolean
|
141 |
+
*/
|
142 |
+
private function isPrefixIdentical(){
|
143 |
+
$db = WPStaging::getInstance()->get("wpdb");
|
144 |
+
|
145 |
+
$livePrefix = $db->prefix;
|
146 |
+
$stagingPrefix = $this->options->prefix;
|
147 |
+
|
148 |
+
if ($livePrefix == $stagingPrefix){
|
149 |
+
return true;
|
150 |
+
}
|
151 |
+
return false;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Start the cloning job
|
156 |
+
*/
|
157 |
+
public function start()
|
158 |
+
{
|
159 |
+
if (null === $this->options->currentJob)
|
160 |
+
{
|
161 |
+
$this->log("Cloning job for {$this->options->clone} finished");
|
162 |
+
return true;
|
163 |
+
}
|
164 |
+
|
165 |
+
$methodName = "job" . ucwords($this->options->currentJob);
|
166 |
+
|
167 |
+
if (!method_exists($this, $methodName))
|
168 |
+
{
|
169 |
+
$this->log("Can't execute job; Job's method {$methodName} is not found");
|
170 |
+
throw new JobNotFoundException($methodName);
|
171 |
+
}
|
172 |
+
|
173 |
+
// Call the job
|
174 |
+
//$this->log("execute job: Job's method {$methodName}");
|
175 |
+
return $this->{$methodName}();
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* @param object $response
|
180 |
+
* @param string $nextJob
|
181 |
+
* @return object
|
182 |
+
*/
|
183 |
+
private function handleJobResponse($response, $nextJob)
|
184 |
+
{
|
185 |
+
// Job is not done
|
186 |
+
if (true !== $response->status)
|
187 |
+
{
|
188 |
+
return $response;
|
189 |
+
}
|
190 |
+
|
191 |
+
$this->options->currentJob = $nextJob;
|
192 |
+
$this->options->currentStep = 0;
|
193 |
+
$this->options->totalSteps = 0;
|
194 |
+
|
195 |
+
// Save options
|
196 |
+
$this->saveOptions();
|
197 |
+
|
198 |
+
return $response;
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Clone Database
|
203 |
+
* @return object
|
204 |
+
*/
|
205 |
+
public function jobDatabase()
|
206 |
+
{
|
207 |
+
$database = new Database();
|
208 |
+
return $this->handleJobResponse($database->start(), "directories");
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Get All Files From Selected Directories Recursively Into a File
|
213 |
+
* @return object
|
214 |
+
*/
|
215 |
+
public function jobDirectories()
|
216 |
+
{
|
217 |
+
$directories = new Directories();
|
218 |
+
return $this->handleJobResponse($directories->start(), "files");
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Copy Files
|
223 |
+
* @return object
|
224 |
+
*/
|
225 |
+
public function jobFiles()
|
226 |
+
{
|
227 |
+
$files = new Files();
|
228 |
+
return $this->handleJobResponse($files->start(), "data");
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Replace Data
|
233 |
+
* @return object
|
234 |
+
*/
|
235 |
+
public function jobData()
|
236 |
+
{
|
237 |
+
$data = new Data();
|
238 |
+
return $this->handleJobResponse($data->start(), "finish");
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Save Clone Data
|
243 |
+
* @return object
|
244 |
+
*/
|
245 |
+
public function jobFinish()
|
246 |
+
{
|
247 |
+
$finish = new Finish();
|
248 |
+
return $this->handleJobResponse($finish->start(), '');
|
249 |
+
}
|
250 |
}
|
apps/Backend/Modules/Jobs/Data.php
CHANGED
@@ -1,409 +1,460 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\Utils\Logger;
|
11 |
-
use WPStaging\WPStaging;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Class Data
|
15 |
-
* @package WPStaging\Backend\Modules\Jobs
|
16 |
-
*/
|
17 |
-
class Data extends JobExecutable
|
18 |
-
{
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @var \wpdb
|
22 |
-
*/
|
23 |
-
private $db;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @var string
|
27 |
-
*/
|
28 |
-
private $prefix;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Initialize
|
32 |
-
*/
|
33 |
-
public function initialize()
|
34 |
-
{
|
35 |
-
$this->db = WPStaging::getInstance()->get("wpdb");
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
*
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
*
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
"
|
71 |
-
"
|
72 |
-
"
|
73 |
-
"
|
74 |
-
"
|
75 |
-
"
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
*
|
84 |
-
*
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
$this->
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
*
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
$this
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
$wpdb
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
$name
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
*
|
166 |
-
* @
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
*
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
//
|
189 |
-
if(
|
190 |
-
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
191 |
-
$this->log( "Updating siteurl and homeurl to " . get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName );
|
192 |
-
// Replace URLs
|
193 |
-
$result = $this->db->query(
|
194 |
-
$this->db->prepare(
|
195 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName
|
196 |
-
)
|
197 |
-
);
|
198 |
-
} else {
|
199 |
-
$this->log( "Search & Replace:: Updating siteurl and homeurl to " . get_home_url() . '/' . $this->options->cloneDirectoryName );
|
200 |
-
// Replace URLs
|
201 |
-
$result = $this->db->query(
|
202 |
-
$this->db->prepare(
|
203 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $this->options->cloneDirectoryName
|
204 |
-
)
|
205 |
-
);
|
206 |
-
}
|
207 |
-
|
208 |
-
|
209 |
-
// All good
|
210 |
-
if( $result ) {
|
211 |
-
return true;
|
212 |
-
}
|
213 |
-
|
214 |
-
$this->log( "Search & Replace: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
215 |
-
return false;
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* Update "wpstg_is_staging_site"
|
220 |
-
* @return bool
|
221 |
-
*/
|
222 |
-
protected function step2()
|
223 |
-
{
|
224 |
-
|
225 |
-
$this->log( "Search & Replace: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
226 |
-
|
227 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
228 |
-
return true;
|
229 |
-
}
|
230 |
-
|
231 |
-
$result = $this->db->query(
|
232 |
-
$this->db->prepare(
|
233 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'",
|
234 |
-
"true"
|
235 |
-
)
|
236 |
-
);
|
237 |
-
|
238 |
-
// No errors but no option name such as wpstg_is_staging_site
|
239 |
-
if ('' === $this->db->last_error && 0 == $result)
|
240 |
-
{
|
241 |
-
$result = $this->db->query(
|
242 |
-
$this->db->prepare(
|
243 |
-
"INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_is_staging_site',%s)",
|
244 |
-
"true"
|
245 |
-
)
|
246 |
-
);
|
247 |
-
}
|
248 |
-
|
249 |
-
// All good
|
250 |
-
if ($result)
|
251 |
-
{
|
252 |
-
return true;
|
253 |
-
}
|
254 |
-
|
255 |
-
$this->log("Search & Replace: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
256 |
-
return false;
|
257 |
-
}
|
258 |
-
|
259 |
-
/**
|
260 |
-
* Update rewrite_rules
|
261 |
-
* @return bool
|
262 |
-
*/
|
263 |
-
protected function step3()
|
264 |
-
{
|
265 |
-
|
266 |
-
$this->log("Search & Replace: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}");
|
267 |
-
|
268 |
-
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
269 |
-
return true;
|
270 |
-
}
|
271 |
-
|
272 |
-
$result = $this->db->query(
|
273 |
-
$this->db->prepare(
|
274 |
-
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'",
|
275 |
-
' '
|
276 |
-
)
|
277 |
-
);
|
278 |
-
|
279 |
-
// All good
|
280 |
-
if ($result)
|
281 |
-
{
|
282 |
-
return true;
|
283 |
-
}
|
284 |
-
|
285 |
-
$this->log("Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
286 |
-
return true;
|
287 |
-
}
|
288 |
-
|
289 |
-
/**
|
290 |
-
* Update Table Prefix in meta_keys
|
291 |
-
* @return bool
|
292 |
-
*/
|
293 |
-
protected function step4() {
|
294 |
-
$this->log( "Search & Replace: Updating {$this->prefix}usermeta db prefix {$this->db->last_error}" );
|
295 |
-
|
296 |
-
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
297 |
-
return true;
|
298 |
-
}
|
299 |
-
|
300 |
-
$resultOptions = $this->db->query(
|
301 |
-
$this->db->prepare(
|
302 |
-
"UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
303 |
-
)
|
304 |
-
);
|
305 |
-
|
306 |
-
if( !$resultOptions ) {
|
307 |
-
$this->log( "Search & Replace: Failed to update usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
308 |
-
return false;
|
309 |
-
}
|
310 |
-
|
311 |
-
$this->log( "Updating {$this->prefix}options, option_name database table prefixes; {$this->db->last_error}" );
|
312 |
-
|
313 |
-
$resultUserMeta = $this->db->query(
|
314 |
-
$this->db->prepare(
|
315 |
-
"UPDATE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
316 |
-
)
|
317 |
-
);
|
318 |
-
|
319 |
-
if( !$resultUserMeta ) {
|
320 |
-
$this->log( "Search & Replace: Failed to update options, option_name database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
321 |
-
return false;
|
322 |
-
}
|
323 |
-
|
324 |
-
return true;
|
325 |
-
}
|
326 |
-
|
327 |
-
/**
|
328 |
-
* Update $table_prefix in wp-config.php
|
329 |
-
* @return bool
|
330 |
-
*/
|
331 |
-
protected function step5()
|
332 |
-
{
|
333 |
-
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
334 |
-
|
335 |
-
$this->log("Search & Replace: Updating table_prefix in {$path} to " . $this->prefix);
|
336 |
-
if (false === ($content = file_get_contents($path)))
|
337 |
-
{
|
338 |
-
$this->log("Search & Replace: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR);
|
339 |
-
return false;
|
340 |
-
}
|
341 |
-
|
342 |
-
// Replace table prefix
|
343 |
-
$content = str_replace('$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content);
|
344 |
-
|
345 |
-
// Replace URLs
|
346 |
-
$content = str_replace(get_home_url(), get_home_url() . '/' . $this->options->cloneDirectoryName, $content);
|
347 |
-
|
348 |
-
if (false === @file_put_contents($path, $content))
|
349 |
-
{
|
350 |
-
$this->log("Search & Replace: Failed to update $table_prefix in {$path} to " .$this->prefix . ". Can't save contents", Logger::TYPE_ERROR);
|
351 |
-
return false;
|
352 |
-
}
|
353 |
-
|
354 |
-
return true;
|
355 |
-
}
|
356 |
-
|
357 |
-
/**
|
358 |
-
* Reset index.php to original file
|
359 |
-
*
|
360 |
-
*
|
361 |
-
* @
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
409 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\Utils\Logger;
|
11 |
+
use WPStaging\WPStaging;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class Data
|
15 |
+
* @package WPStaging\Backend\Modules\Jobs
|
16 |
+
*/
|
17 |
+
class Data extends JobExecutable
|
18 |
+
{
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var \wpdb
|
22 |
+
*/
|
23 |
+
private $db;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
private $prefix;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Initialize
|
32 |
+
*/
|
33 |
+
public function initialize()
|
34 |
+
{
|
35 |
+
$this->db = WPStaging::getInstance()->get("wpdb");
|
36 |
+
|
37 |
+
$this->prefix = $this->options->prefix;
|
38 |
+
|
39 |
+
// Fix current step
|
40 |
+
if (0 == $this->options->currentStep)
|
41 |
+
{
|
42 |
+
$this->options->currentStep = 1;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
48 |
+
* @return void
|
49 |
+
*/
|
50 |
+
protected function calculateTotalSteps()
|
51 |
+
{
|
52 |
+
$this->options->totalSteps = 6;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Start Module
|
57 |
+
* @return object
|
58 |
+
*/
|
59 |
+
public function start()
|
60 |
+
{
|
61 |
+
// Execute steps
|
62 |
+
$this->run();
|
63 |
+
|
64 |
+
// Save option, progress
|
65 |
+
$this->saveOptions();
|
66 |
+
|
67 |
+
// Prepare response
|
68 |
+
// $this->response = array(
|
69 |
+
// "status" => true,
|
70 |
+
// "percentage" => 100,
|
71 |
+
// "total" => $this->options->totalSteps,
|
72 |
+
// "step" => $this->options->totalSteps,
|
73 |
+
// "last_msg" => $this->logger->getLastLogMsg(),
|
74 |
+
// "running_time" => $this->time() - time(),
|
75 |
+
// "job_done" => true
|
76 |
+
// );
|
77 |
+
|
78 |
+
return (object) $this->response;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Execute the Current Step
|
83 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
84 |
+
* @return bool
|
85 |
+
*/
|
86 |
+
protected function execute()
|
87 |
+
{
|
88 |
+
// Fatal error. Let this happen never and break here immediately
|
89 |
+
if ($this->isRoot()){
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
// Over limits threshold
|
94 |
+
if ($this->isOverThreshold())
|
95 |
+
{
|
96 |
+
// Prepare response and save current progress
|
97 |
+
$this->prepareResponse(false, false);
|
98 |
+
$this->saveOptions();
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
// No more steps, finished
|
103 |
+
if ($this->isFinished())
|
104 |
+
{
|
105 |
+
$this->prepareResponse(true, false);
|
106 |
+
return false;
|
107 |
+
}
|
108 |
+
|
109 |
+
// Execute step
|
110 |
+
$stepMethodName = "step" . $this->options->currentStep;
|
111 |
+
if (!$this->{$stepMethodName}())
|
112 |
+
{
|
113 |
+
$this->prepareResponse(false, false);
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
|
117 |
+
// Prepare Response
|
118 |
+
$this->prepareResponse();
|
119 |
+
|
120 |
+
// Not finished
|
121 |
+
return true;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Checks Whether There is Any Job to Execute or Not
|
126 |
+
* @return bool
|
127 |
+
*/
|
128 |
+
private function isFinished()
|
129 |
+
{
|
130 |
+
return (
|
131 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
132 |
+
!method_exists($this, "step" . $this->options->currentStep)
|
133 |
+
);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Check if current operation is done on the root folder or on the live DB
|
138 |
+
* @return boolean
|
139 |
+
*/
|
140 |
+
private function isRoot(){
|
141 |
+
|
142 |
+
// Prefix is the same as the one of live site
|
143 |
+
$wpdb = WPStaging::getInstance()->get("wpdb");
|
144 |
+
if ($wpdb->prefix === $this->prefix){
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
|
148 |
+
// CloneName is empty
|
149 |
+
$name = (array)$this->options->cloneDirectoryName;
|
150 |
+
if (empty($name)){
|
151 |
+
return true;
|
152 |
+
}
|
153 |
+
|
154 |
+
// Live Path === Staging path
|
155 |
+
if (get_home_url() . $this->options->cloneDirectoryName === get_home_url()){
|
156 |
+
return true;
|
157 |
+
}
|
158 |
+
|
159 |
+
return false;
|
160 |
+
}
|
161 |
+
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Check if table exists
|
165 |
+
* @param string $table
|
166 |
+
* @return boolean
|
167 |
+
*/
|
168 |
+
protected function isTable($table){
|
169 |
+
if($this->db->get_var("SHOW TABLES LIKE '{$table}'") != $table ){
|
170 |
+
$this->log( "Table {$table} does not exists", Logger::TYPE_ERROR );
|
171 |
+
return false;
|
172 |
+
}
|
173 |
+
return true;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Replace "siteurl"
|
178 |
+
* @return bool
|
179 |
+
*/
|
180 |
+
protected function step1() {
|
181 |
+
$this->log( "Search & Replace: Updating siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_INFO );
|
182 |
+
|
183 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
184 |
+
return true;
|
185 |
+
}
|
186 |
+
|
187 |
+
// Installed in sub-directory
|
188 |
+
//if( isset( $this->settings->wpSubDirectory ) && "1" === $this->settings->wpSubDirectory ) {
|
189 |
+
if( $this->isSubDir() ) {
|
190 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
191 |
+
$this->log( "Updating siteurl and homeurl to " . get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName );
|
192 |
+
// Replace URLs
|
193 |
+
$result = $this->db->query(
|
194 |
+
$this->db->prepare(
|
195 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $subDirectory . $this->options->cloneDirectoryName
|
196 |
+
)
|
197 |
+
);
|
198 |
+
} else {
|
199 |
+
$this->log( "Search & Replace:: Updating siteurl and homeurl to " . get_home_url() . '/' . $this->options->cloneDirectoryName );
|
200 |
+
// Replace URLs
|
201 |
+
$result = $this->db->query(
|
202 |
+
$this->db->prepare(
|
203 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'siteurl' or option_name='home'", get_home_url() . '/' . $this->options->cloneDirectoryName
|
204 |
+
)
|
205 |
+
);
|
206 |
+
}
|
207 |
+
|
208 |
+
|
209 |
+
// All good
|
210 |
+
if( $result ) {
|
211 |
+
return true;
|
212 |
+
}
|
213 |
+
|
214 |
+
$this->log( "Search & Replace: Failed to update siteurl and homeurl in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR );
|
215 |
+
return false;
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Update "wpstg_is_staging_site"
|
220 |
+
* @return bool
|
221 |
+
*/
|
222 |
+
protected function step2()
|
223 |
+
{
|
224 |
+
|
225 |
+
$this->log( "Search & Replace: Updating row wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}" );
|
226 |
+
|
227 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
228 |
+
return true;
|
229 |
+
}
|
230 |
+
|
231 |
+
$result = $this->db->query(
|
232 |
+
$this->db->prepare(
|
233 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_is_staging_site'",
|
234 |
+
"true"
|
235 |
+
)
|
236 |
+
);
|
237 |
+
|
238 |
+
// No errors but no option name such as wpstg_is_staging_site
|
239 |
+
if ('' === $this->db->last_error && 0 == $result)
|
240 |
+
{
|
241 |
+
$result = $this->db->query(
|
242 |
+
$this->db->prepare(
|
243 |
+
"INSERT INTO {$this->prefix}options (option_name,option_value) VALUES ('wpstg_is_staging_site',%s)",
|
244 |
+
"true"
|
245 |
+
)
|
246 |
+
);
|
247 |
+
}
|
248 |
+
|
249 |
+
// All good
|
250 |
+
if ($result)
|
251 |
+
{
|
252 |
+
return true;
|
253 |
+
}
|
254 |
+
|
255 |
+
$this->log("Search & Replace: Failed to update wpstg_is_staging_site in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
256 |
+
return false;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Update rewrite_rules
|
261 |
+
* @return bool
|
262 |
+
*/
|
263 |
+
protected function step3()
|
264 |
+
{
|
265 |
+
|
266 |
+
$this->log("Search & Replace: Updating rewrite_rules in {$this->prefix}options {$this->db->last_error}");
|
267 |
+
|
268 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
269 |
+
return true;
|
270 |
+
}
|
271 |
+
|
272 |
+
$result = $this->db->query(
|
273 |
+
$this->db->prepare(
|
274 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'rewrite_rules'",
|
275 |
+
' '
|
276 |
+
)
|
277 |
+
);
|
278 |
+
|
279 |
+
// All good
|
280 |
+
if ($result)
|
281 |
+
{
|
282 |
+
return true;
|
283 |
+
}
|
284 |
+
|
285 |
+
$this->log("Failed to update rewrite_rules in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_ERROR);
|
286 |
+
return true;
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Update Table Prefix in meta_keys
|
291 |
+
* @return bool
|
292 |
+
*/
|
293 |
+
protected function step4() {
|
294 |
+
$this->log( "Search & Replace: Updating {$this->prefix}usermeta db prefix {$this->db->last_error}" );
|
295 |
+
|
296 |
+
if( false === $this->isTable( $this->prefix . 'usermeta' ) ) {
|
297 |
+
return true;
|
298 |
+
}
|
299 |
+
|
300 |
+
$resultOptions = $this->db->query(
|
301 |
+
$this->db->prepare(
|
302 |
+
"UPDATE {$this->prefix}usermeta SET meta_key = replace(meta_key, %s, %s) WHERE meta_key LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
303 |
+
)
|
304 |
+
);
|
305 |
+
|
306 |
+
if( !$resultOptions ) {
|
307 |
+
$this->log( "Search & Replace: Failed to update usermeta meta_key database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
308 |
+
return false;
|
309 |
+
}
|
310 |
+
|
311 |
+
$this->log( "Updating {$this->prefix}options, option_name database table prefixes; {$this->db->last_error}" );
|
312 |
+
|
313 |
+
$resultUserMeta = $this->db->query(
|
314 |
+
$this->db->prepare(
|
315 |
+
"UPDATE {$this->prefix}options SET option_name= replace(option_name, %s, %s) WHERE option_name LIKE %s", $this->db->prefix, $this->prefix, $this->db->prefix . "_%"
|
316 |
+
)
|
317 |
+
);
|
318 |
+
|
319 |
+
if( !$resultUserMeta ) {
|
320 |
+
$this->log( "Search & Replace: Failed to update options, option_name database table prefixes; {$this->db->last_error}", Logger::TYPE_ERROR );
|
321 |
+
return false;
|
322 |
+
}
|
323 |
+
|
324 |
+
return true;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Update $table_prefix in wp-config.php
|
329 |
+
* @return bool
|
330 |
+
*/
|
331 |
+
protected function step5()
|
332 |
+
{
|
333 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
334 |
+
|
335 |
+
$this->log("Search & Replace: Updating table_prefix in {$path} to " . $this->prefix);
|
336 |
+
if (false === ($content = file_get_contents($path)))
|
337 |
+
{
|
338 |
+
$this->log("Search & Replace: Failed to update table_prefix in {$path}. Can't read contents", Logger::TYPE_ERROR);
|
339 |
+
return false;
|
340 |
+
}
|
341 |
+
|
342 |
+
// Replace table prefix
|
343 |
+
$content = str_replace('$table_prefix', '$table_prefix = \'' . $this->prefix . '\';//', $content);
|
344 |
+
|
345 |
+
// Replace URLs
|
346 |
+
$content = str_replace(get_home_url(), get_home_url() . '/' . $this->options->cloneDirectoryName, $content);
|
347 |
+
|
348 |
+
if (false === @file_put_contents($path, $content))
|
349 |
+
{
|
350 |
+
$this->log("Search & Replace: Failed to update $table_prefix in {$path} to " .$this->prefix . ". Can't save contents", Logger::TYPE_ERROR);
|
351 |
+
return false;
|
352 |
+
}
|
353 |
+
|
354 |
+
return true;
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Reset index.php to original file
|
359 |
+
* This is needed if live site is located in subfolder
|
360 |
+
* Check first if main wordpress is used in subfolder and index.php in parent directory
|
361 |
+
* @see: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
|
362 |
+
* @return bool
|
363 |
+
*/
|
364 |
+
protected function step6()
|
365 |
+
{
|
366 |
+
// No settings, all good
|
367 |
+
// if (!isset($this->settings->wpSubDirectory) || "1" !== $this->settings->wpSubDirectory)
|
368 |
+
// {
|
369 |
+
// $this->log("Search & Replace: WP installation is not in a subdirectory! All good, skipping this step");
|
370 |
+
// return true;
|
371 |
+
// }
|
372 |
+
if (!$this->isSubDir())
|
373 |
+
{
|
374 |
+
$this->debugLog("Search & Replace: WP installation is not in a subdirectory! All good, skipping this step");
|
375 |
+
return true;
|
376 |
+
}
|
377 |
+
|
378 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/index.php";
|
379 |
+
|
380 |
+
if (false === ($content = file_get_contents($path)))
|
381 |
+
{
|
382 |
+
$this->log("Search & Replace: Failed to reset {$path} for sub directory; can't read contents", Logger::TYPE_ERROR);
|
383 |
+
return false;
|
384 |
+
}
|
385 |
+
|
386 |
+
|
387 |
+
if (!preg_match("/(require(.*)wp-blog-header.php' \);)/", $content, $matches))
|
388 |
+
{
|
389 |
+
$this->log(
|
390 |
+
"Search & Replace: Failed to reset index.php for sub directory; wp-blog-header.php is missing",
|
391 |
+
Logger::TYPE_ERROR
|
392 |
+
);
|
393 |
+
return false;
|
394 |
+
}
|
395 |
+
$this->log("Search & Replace: WP installation is in a subdirectory. Progressing...");
|
396 |
+
|
397 |
+
$pattern = "/require(.*) dirname(.*) __FILE__ (.*) \. '(.*)wp-blog-header.php'(.*);/";
|
398 |
+
|
399 |
+
$replace = "require( dirname( __FILE__ ) . '/wp-blog-header.php' ); // " . $matches[0];
|
400 |
+
$replace.= " // Changed by WP-Staging";
|
401 |
+
|
402 |
+
|
403 |
+
|
404 |
+
if (null === ($content = preg_replace(array($pattern), $replace, $content)))
|
405 |
+
{
|
406 |
+
$this->log("Search & Replace: Failed to reset index.php for sub directory; replacement failed", Logger::TYPE_ERROR);
|
407 |
+
return false;
|
408 |
+
}
|
409 |
+
|
410 |
+
if (false === @file_put_contents($path, $content))
|
411 |
+
{
|
412 |
+
$this->log("Search & Replace: Failed to reset index.php for sub directory; can't save contents", Logger::TYPE_ERROR);
|
413 |
+
return false;
|
414 |
+
}
|
415 |
+
$this->Log("Search & Replace: Finished Step 6 successfully");
|
416 |
+
|
417 |
+
return true;
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* Update wpstg_rmpermalinks_executed
|
422 |
+
* @return bool
|
423 |
+
*/
|
424 |
+
protected function step7()
|
425 |
+
{
|
426 |
+
|
427 |
+
$this->log("Search & Replace: Updating wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}");
|
428 |
+
|
429 |
+
if( false === $this->isTable( $this->prefix . 'options' ) ) {
|
430 |
+
return true;
|
431 |
+
}
|
432 |
+
|
433 |
+
$result = $this->db->query(
|
434 |
+
$this->db->prepare(
|
435 |
+
"UPDATE {$this->prefix}options SET option_value = %s WHERE option_name = 'wpstg_rmpermalinks_executed'",
|
436 |
+
' '
|
437 |
+
)
|
438 |
+
);
|
439 |
+
|
440 |
+
// All good
|
441 |
+
if ($result)
|
442 |
+
{
|
443 |
+
return true;
|
444 |
+
}
|
445 |
+
|
446 |
+
$this->log("Failed to update wpstg_rmpermalinks_executed in {$this->prefix}options {$this->db->last_error}", Logger::TYPE_WARNING);
|
447 |
+
return true;
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Check if WP is installed in subdir
|
452 |
+
* @return boolean
|
453 |
+
*/
|
454 |
+
protected function isSubDir(){
|
455 |
+
if ( get_option( 'siteurl' ) !== get_option( 'home' ) ) {
|
456 |
+
return true;
|
457 |
+
}
|
458 |
+
return false;
|
459 |
+
}
|
460 |
}
|
apps/Backend/Modules/Jobs/Database.php
CHANGED
@@ -1,263 +1,265 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
*
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
$this->
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
*
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
*
|
51 |
-
*
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
$this->
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
*
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
$
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
*
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
*
|
185 |
-
* @
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
$this->
|
197 |
-
|
198 |
-
$this->
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
*
|
250 |
-
* @
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
|
|
|
|
263 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Strings;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class Database
|
15 |
+
* @package WPStaging\Backend\Modules\Jobs
|
16 |
+
*/
|
17 |
+
class Database extends JobExecutable
|
18 |
+
{
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var int
|
22 |
+
*/
|
23 |
+
private $total = 0;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var \WPDB
|
27 |
+
*/
|
28 |
+
private $db;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Initialize
|
32 |
+
*/
|
33 |
+
public function initialize()
|
34 |
+
{
|
35 |
+
// Variables
|
36 |
+
$this->total = count($this->options->tables);
|
37 |
+
$this->db = WPStaging::getInstance()->get("wpdb");
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
+
protected function calculateTotalSteps()
|
45 |
+
{
|
46 |
+
$this->options->totalSteps = $this->total === 0 ? 1 : $this->total;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Execute the Current Step
|
51 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
52 |
+
* @return bool
|
53 |
+
*/
|
54 |
+
protected function execute()
|
55 |
+
{
|
56 |
+
// Over limits threshold
|
57 |
+
if ($this->isOverThreshold())
|
58 |
+
{
|
59 |
+
// Prepare response and save current progress
|
60 |
+
$this->prepareResponse(false, false);
|
61 |
+
$this->saveOptions();
|
62 |
+
return false;
|
63 |
+
}
|
64 |
+
|
65 |
+
// No more steps, finished
|
66 |
+
if ($this->options->currentStep > $this->total || !isset($this->options->tables[$this->options->currentStep]))
|
67 |
+
{
|
68 |
+
$this->prepareResponse(true, false);
|
69 |
+
return false;
|
70 |
+
}
|
71 |
+
|
72 |
+
// Table is excluded
|
73 |
+
// if (in_array($this->options->tables[$this->options->currentStep]->name, $this->options->excludedTables))
|
74 |
+
// {
|
75 |
+
// $this->prepareResponse();
|
76 |
+
// return true;
|
77 |
+
// }
|
78 |
+
|
79 |
+
// Copy table
|
80 |
+
//if (!$this->copyTable($this->options->tables[$this->options->currentStep]->name))
|
81 |
+
if (!$this->copyTable($this->options->tables[$this->options->currentStep]))
|
82 |
+
{
|
83 |
+
// Prepare Response
|
84 |
+
$this->prepareResponse(false, false);
|
85 |
+
|
86 |
+
// Not finished
|
87 |
+
return true;
|
88 |
+
}
|
89 |
+
|
90 |
+
// Prepare Response
|
91 |
+
$this->prepareResponse();
|
92 |
+
|
93 |
+
// Not finished
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Get new prefix for the staging site
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
private function getStagingPrefix(){
|
102 |
+
$stagingPrefix = $this->options->prefix;
|
103 |
+
// Make sure prefix of staging site is NEVER identical to prefix of live site!
|
104 |
+
if ( $stagingPrefix == $this->db->prefix ){
|
105 |
+
wp_die('Fatal error 7: The new database table prefix '. $stagingPrefix .' would be identical to the table prefix of the live site. Please open a support ticket to support@wp-staging.com');
|
106 |
+
}
|
107 |
+
return $stagingPrefix;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* No worries, SQL queries don't eat from PHP execution time!
|
112 |
+
* @param string $tableName
|
113 |
+
* @return bool
|
114 |
+
*/
|
115 |
+
private function copyTable($tableName)
|
116 |
+
{
|
117 |
+
|
118 |
+
$strings = new Strings();
|
119 |
+
$tableName = is_object($tableName) ? $tableName->name : $tableName;
|
120 |
+
$newTableName = $this->getStagingPrefix() . $strings->str_replace_first($this->db->prefix, null, $tableName);
|
121 |
+
|
122 |
+
// Drop table if necessary
|
123 |
+
$this->dropTable($newTableName);
|
124 |
+
|
125 |
+
// Save current job
|
126 |
+
$this->setJob($newTableName);
|
127 |
+
|
128 |
+
// Beginning of the job
|
129 |
+
if (!$this->startJob($newTableName, $tableName))
|
130 |
+
{
|
131 |
+
return true;
|
132 |
+
}
|
133 |
+
|
134 |
+
// Copy data
|
135 |
+
$this->copyData($newTableName, $tableName);
|
136 |
+
|
137 |
+
// Finis the step
|
138 |
+
return $this->finishStep();
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Copy data from old table to new table
|
143 |
+
* @param string $new
|
144 |
+
* @param string $old
|
145 |
+
*/
|
146 |
+
private function copyData($new, $old)
|
147 |
+
{
|
148 |
+
$rows = $this->options->job->start+$this->settings->queryLimit;
|
149 |
+
$this->log(
|
150 |
+
"DB Copy: {$old} as {$new} between {$this->options->job->start} to {$rows} records"
|
151 |
+
);
|
152 |
+
|
153 |
+
$limitation = '';
|
154 |
+
|
155 |
+
if (0 < (int) $this->settings->queryLimit)
|
156 |
+
{
|
157 |
+
$limitation = " LIMIT {$this->settings->queryLimit} OFFSET {$this->options->job->start}";
|
158 |
+
}
|
159 |
+
|
160 |
+
$this->db->query(
|
161 |
+
"INSERT INTO {$new} SELECT * FROM {$old} {$limitation}"
|
162 |
+
);
|
163 |
+
|
164 |
+
// Set new offset
|
165 |
+
$this->options->job->start += $this->settings->queryLimit;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Set the job
|
170 |
+
* @param string $table
|
171 |
+
*/
|
172 |
+
private function setJob($table)
|
173 |
+
{
|
174 |
+
if (isset($this->options->job->current))
|
175 |
+
{
|
176 |
+
return;
|
177 |
+
}
|
178 |
+
|
179 |
+
$this->options->job->current = $table;
|
180 |
+
$this->options->job->start = 0;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Start Job
|
185 |
+
* @param string $new
|
186 |
+
* @param string $old
|
187 |
+
* @return bool
|
188 |
+
*/
|
189 |
+
private function startJob($new, $old)
|
190 |
+
{
|
191 |
+
if (0 != $this->options->job->start)
|
192 |
+
{
|
193 |
+
return true;
|
194 |
+
}
|
195 |
+
|
196 |
+
$this->log("DB Copy: Creating table {$new} like {$old}");
|
197 |
+
|
198 |
+
$this->db->query("CREATE TABLE {$new} LIKE {$old}");
|
199 |
+
|
200 |
+
$this->options->job->total = (int) $this->db->get_var("SELECT COUNT(1) FROM {$old}");
|
201 |
+
|
202 |
+
if (0 == $this->options->job->total)
|
203 |
+
{
|
204 |
+
$this->finishStep();
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
|
208 |
+
return true;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Finish the step
|
213 |
+
*/
|
214 |
+
private function finishStep()
|
215 |
+
{
|
216 |
+
// This job is not finished yet
|
217 |
+
if ($this->options->job->total > $this->options->job->start)
|
218 |
+
{
|
219 |
+
return false;
|
220 |
+
}
|
221 |
+
|
222 |
+
// Add it to cloned tables listing
|
223 |
+
$this->options->clonedTables[] = $this->options->tables[$this->options->currentStep];
|
224 |
+
|
225 |
+
// Reset job
|
226 |
+
$this->options->job = new \stdClass();
|
227 |
+
|
228 |
+
return true;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Drop table if necessary
|
233 |
+
* @param string $new
|
234 |
+
*/
|
235 |
+
private function dropTable($new)
|
236 |
+
{
|
237 |
+
$old = $this->db->get_var($this->db->prepare("SHOW TABLES LIKE %s", $new));
|
238 |
+
|
239 |
+
if (!$this->shouldDropTable($new, $old))
|
240 |
+
{
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
|
244 |
+
$this->log("DB Copy: {$new} already exists, dropping it first");
|
245 |
+
$this->db->query("DROP TABLE {$new}");
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Check if table needs to be dropped
|
250 |
+
* @param string $new
|
251 |
+
* @param string $old
|
252 |
+
* @return bool
|
253 |
+
*/
|
254 |
+
private function shouldDropTable($new, $old)
|
255 |
+
{
|
256 |
+
return (
|
257 |
+
$old === $new &&
|
258 |
+
(
|
259 |
+
!isset($this->options->job->current) ||
|
260 |
+
!isset($this->options->job->start) ||
|
261 |
+
0 == $this->options->job->start
|
262 |
+
)
|
263 |
+
);
|
264 |
+
}
|
265 |
}
|
apps/Backend/Modules/Jobs/Delete.php
CHANGED
@@ -1,497 +1,497 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
-
|
5 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
6 |
-
use WPStaging\Utils\Directories;
|
7 |
-
use WPStaging\Utils\Logger;
|
8 |
-
use WPStaging\WPStaging;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class Delete
|
12 |
-
* @package WPStaging\Backend\Modules\Jobs
|
13 |
-
*/
|
14 |
-
class Delete extends Job {
|
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 |
-
*
|
38 |
-
* @var object
|
39 |
-
*/
|
40 |
-
public $wpdb;
|
41 |
-
|
42 |
-
public function __construct() {
|
43 |
-
parent::__construct();
|
44 |
-
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Sets Clone and Table Records
|
49 |
-
* @param null|array $clone
|
50 |
-
*/
|
51 |
-
public function setData($clone = null) {
|
52 |
-
if (!is_array($clone)) {
|
53 |
-
$this->getCloneRecords();
|
54 |
-
} else {
|
55 |
-
$this->clone = (object) $clone;
|
56 |
-
$this->forceDeleteDirectories = true;
|
57 |
-
}
|
58 |
-
|
59 |
-
$this->getTableRecords();
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Get clone
|
64 |
-
* @param null|string $name
|
65 |
-
* @throws CloneNotFoundException
|
66 |
-
*/
|
67 |
-
private function getCloneRecords($name = null) {
|
68 |
-
if (null === $name && !isset($_POST["clone"])) {
|
69 |
-
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
70 |
-
throw new CloneNotFoundException();
|
71 |
-
}
|
72 |
-
|
73 |
-
if (null === $name) {
|
74 |
-
$name = $_POST["clone"];
|
75 |
-
}
|
76 |
-
|
77 |
-
$clones = get_option("wpstg_existing_clones_beta", array());
|
78 |
-
|
79 |
-
if (empty($clones) || !isset($clones[$name])) {
|
80 |
-
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
81 |
-
throw new CloneNotFoundException();
|
82 |
-
}
|
83 |
-
|
84 |
-
$this->clone = $clones[$name];
|
85 |
-
$this->clone["name"] = $name;
|
86 |
-
|
87 |
-
$this->clone = (object) $this->clone;
|
88 |
-
|
89 |
-
unset($clones);
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Get Tables
|
94 |
-
*/
|
95 |
-
private function getTableRecords() {
|
96 |
-
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
97 |
-
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
98 |
-
|
99 |
-
$stagingPrefix = $this->getStagingPrefix();
|
100 |
-
|
101 |
-
$tables = $this->wpdb->get_results("SHOW TABLE STATUS LIKE '{$stagingPrefix}%'");
|
102 |
-
|
103 |
-
$this->tables = array();
|
104 |
-
|
105 |
-
foreach ($tables as $table) {
|
106 |
-
$this->tables[] = array(
|
107 |
-
"name" => $table->Name,
|
108 |
-
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
109 |
-
);
|
110 |
-
}
|
111 |
-
|
112 |
-
$this->tables = json_decode(json_encode($this->tables));
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Check and return prefix of the staging site
|
117 |
-
*/
|
118 |
-
public function getStagingPrefix() {
|
119 |
-
// Prefix not defined! Happens if staging site has ben generated with older version of wpstg
|
120 |
-
// Try to get staging prefix from wp-config.php of staging site
|
121 |
-
if (empty($this->clone->prefix)) {
|
122 |
-
// Throw error
|
123 |
-
$path = ABSPATH . $this->clone->directoryName . "/wp-config.php";
|
124 |
-
if (false === ($content = @file_get_contents($path))) {
|
125 |
-
$this->log("Can not open {$path}. Can't read contents", Logger::TYPE_ERROR);
|
126 |
-
// Create a random prefix which hopefully never exists.
|
127 |
-
$this->clone->prefix = rand(7, 15) . '_';
|
128 |
-
} else {
|
129 |
-
|
130 |
-
// Get prefix from wp-config.php
|
131 |
-
//preg_match_all("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
132 |
-
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
133 |
-
//wp_die(var_dump($matches));
|
134 |
-
|
135 |
-
if (!empty($matches[1])) {
|
136 |
-
$this->clone->prefix = $matches[1];
|
137 |
-
} else {
|
138 |
-
$this->log("Fatal Error: Can not delete staging site. Can not find Prefix. '{$matches[1]}'. Stopping for security reasons. Creating a new staging site will likely resolve this the next time. Contact support@wp-staging.com");
|
139 |
-
// Create a random prefix which hopefully never exists.
|
140 |
-
return $this->clone->prefix = rand(7, 15) . '_';
|
141 |
-
}
|
142 |
-
}
|
143 |
-
}
|
144 |
-
|
145 |
-
// Check if staging prefix is the same as the live prefix
|
146 |
-
if ($this->wpdb->prefix == $this->clone->prefix) {
|
147 |
-
$this->log("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
148 |
-
wp_die("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
149 |
-
}
|
150 |
-
|
151 |
-
// Else
|
152 |
-
return $this->clone->prefix;
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Format bytes into human readable form
|
157 |
-
* @param int $bytes
|
158 |
-
* @param int $precision
|
159 |
-
* @return string
|
160 |
-
*/
|
161 |
-
public function formatSize($bytes, $precision = 2) {
|
162 |
-
if ((int) $bytes < 1) {
|
163 |
-
return '';
|
164 |
-
}
|
165 |
-
|
166 |
-
$units = array('B', "KB", "MB", "GB", "TB");
|
167 |
-
|
168 |
-
$bytes = (int) $bytes;
|
169 |
-
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
170 |
-
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
171 |
-
|
172 |
-
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* @return false
|
177 |
-
*/
|
178 |
-
public function getClone() {
|
179 |
-
return $this->clone;
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* @return null|object
|
184 |
-
*/
|
185 |
-
public function getTables() {
|
186 |
-
return $this->tables;
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* Start Module
|
191 |
-
* @param null|array $clone
|
192 |
-
* @return bool
|
193 |
-
*/
|
194 |
-
public function start($clone = null) {
|
195 |
-
// Set data
|
196 |
-
$this->setData($clone);
|
197 |
-
|
198 |
-
// Get the job first
|
199 |
-
$this->getJob();
|
200 |
-
|
201 |
-
$method = "delete" . ucwords($this->job->current);
|
202 |
-
return $this->{$method}();
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Get job data
|
207 |
-
*/
|
208 |
-
private function getJob() {
|
209 |
-
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
210 |
-
|
211 |
-
|
212 |
-
if (null !== $this->job) {
|
213 |
-
return;
|
214 |
-
}
|
215 |
-
|
216 |
-
// Generate JOB
|
217 |
-
$this->job = (object) array(
|
218 |
-
"current" => "tables",
|
219 |
-
"nextDirectoryToDelete" => $this->clone->path,
|
220 |
-
"name" => $this->clone->name
|
221 |
-
);
|
222 |
-
|
223 |
-
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
224 |
-
}
|
225 |
-
|
226 |
-
/**
|
227 |
-
* @return bool
|
228 |
-
*/
|
229 |
-
private function updateJob() {
|
230 |
-
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
231 |
-
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
232 |
-
}
|
233 |
-
|
234 |
-
/**
|
235 |
-
* @return array
|
236 |
-
*/
|
237 |
-
private function getTablesToRemove() {
|
238 |
-
$tables = $this->getTableNames();
|
239 |
-
|
240 |
-
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"])) {
|
241 |
-
return $tables;
|
242 |
-
}
|
243 |
-
|
244 |
-
return array_diff($tables, $_POST["excludedTables"]);
|
245 |
-
}
|
246 |
-
|
247 |
-
/**
|
248 |
-
* @return array
|
249 |
-
*/
|
250 |
-
private function getTableNames() {
|
251 |
-
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
252 |
-
return ($value->name);
|
253 |
-
}, $this->tables);
|
254 |
-
}
|
255 |
-
|
256 |
-
/**
|
257 |
-
* Delete Tables
|
258 |
-
*/
|
259 |
-
public function deleteTables() {
|
260 |
-
if ($this->isOverThreshold()) {
|
261 |
-
return;
|
262 |
-
}
|
263 |
-
|
264 |
-
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
265 |
-
|
266 |
-
foreach ($this->getTablesToRemove() as $table) {
|
267 |
-
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
268 |
-
if ($this->startsWith($table, $this->wpdb->prefix)) {
|
269 |
-
$this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
|
270 |
-
return false;
|
271 |
-
} else {
|
272 |
-
$this->wpdb->query("DROP TABLE {$table}");
|
273 |
-
}
|
274 |
-
}
|
275 |
-
|
276 |
-
// Move on to the next
|
277 |
-
$this->job->current = "directory";
|
278 |
-
$this->updateJob();
|
279 |
-
}
|
280 |
-
|
281 |
-
/**
|
282 |
-
* Check if a strings start with a specific string
|
283 |
-
* @param string $haystack
|
284 |
-
* @param string $needle
|
285 |
-
* @return bool
|
286 |
-
*/
|
287 |
-
protected function startsWith($haystack, $needle) {
|
288 |
-
$length = strlen($needle);
|
289 |
-
return (substr($haystack, 0, $length) === $needle);
|
290 |
-
}
|
291 |
-
|
292 |
-
/**
|
293 |
-
* Delete complete directory including all files and subfolders
|
294 |
-
*
|
295 |
-
* @throws InvalidArgumentException
|
296 |
-
*/
|
297 |
-
public function deleteDirectory() {
|
298 |
-
if ($this->isFatalError()) {
|
299 |
-
$this->returnException('Can not delete directory: ' . $this->clone->path . '. This seems to be the root directory. Please contact support@wp-staging.com');
|
300 |
-
throw new \Exception('Can not delete directory: ' . $this->clone->path . ' This seems to be the root directory. Please contact support@wp-staging.com');
|
301 |
-
}
|
302 |
-
// Finished or path does not exist
|
303 |
-
if (
|
304 |
-
empty($this->clone->path) ||
|
305 |
-
$this->clone->path == get_home_path() ||
|
306 |
-
!is_dir($this->clone->path)) {
|
307 |
-
|
308 |
-
$this->job->current = "finish";
|
309 |
-
$this->updateJob();
|
310 |
-
return $this->returnFinish();
|
311 |
-
}
|
312 |
-
|
313 |
-
$this->log("Delete staging site: " . $this->clone->path, Logger::TYPE_INFO);
|
314 |
-
|
315 |
-
// Just to make sure the root dir is never deleted!
|
316 |
-
if ($this->clone->path == get_home_path()) {
|
317 |
-
$this->log("Fatal Error 8: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
318 |
-
$this->returnException('Fatal Error 8: Trying to delete root of WP installation!');
|
319 |
-
}
|
320 |
-
|
321 |
-
// Check if threshold is reached
|
322 |
-
if ($this->isOverThreshold()) {
|
323 |
-
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
324 |
-
return;
|
325 |
-
}
|
326 |
-
|
327 |
-
$di = new \RecursiveDirectoryIterator($this->clone->path, \FilesystemIterator::SKIP_DOTS);
|
328 |
-
$ri = new \RecursiveIteratorIterator($di, \RecursiveIteratorIterator::CHILD_FIRST);
|
329 |
-
foreach ($ri as $file) {
|
330 |
-
//$file->isDir() ? @rmdir($file) : unlink($file);
|
331 |
-
$this->deleteFile($file);
|
332 |
-
if ($this->isOverThreshold()) {
|
333 |
-
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
334 |
-
return;
|
335 |
-
}
|
336 |
-
}
|
337 |
-
|
338 |
-
if (@rmdir($this->clone->path)) {
|
339 |
-
return $this->returnFinish();
|
340 |
-
}
|
341 |
-
return;
|
342 |
-
}
|
343 |
-
|
344 |
-
/**
|
345 |
-
* Delete file
|
346 |
-
* @param object iterator $file
|
347 |
-
*/
|
348 |
-
private function deleteFile($file) {
|
349 |
-
if ($file->isDir()) {
|
350 |
-
if (!@rmdir($file)) {
|
351 |
-
$this->returnException('Permission Error: Can not delete folder ' . $file);
|
352 |
-
}
|
353 |
-
} else {
|
354 |
-
if (!unlink($file)) {
|
355 |
-
$this->returnException('Permission Error: Can not delete file ' . $file);
|
356 |
-
}
|
357 |
-
}
|
358 |
-
}
|
359 |
-
|
360 |
-
/**
|
361 |
-
* @return bool
|
362 |
-
*/
|
363 |
-
public function isDirectoryDeletingFinished() {
|
364 |
-
return (
|
365 |
-
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
366 |
-
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
367 |
-
);
|
368 |
-
}
|
369 |
-
|
370 |
-
/**
|
371 |
-
* Delete contents of the directory if there are no directories in it and then delete itself
|
372 |
-
* @param string $path
|
373 |
-
* @return mixed
|
374 |
-
*/
|
375 |
-
// private function processDirectory($path) {
|
376 |
-
// // We hit the limit, stop
|
377 |
-
// if ($this->shouldStop($path)) {
|
378 |
-
// $this->updateJob();
|
379 |
-
// return false;
|
380 |
-
// }
|
381 |
-
//
|
382 |
-
// $this->totalRecursion++;
|
383 |
-
//
|
384 |
-
// $contents = new \DirectoryIterator($path);
|
385 |
-
//
|
386 |
-
// foreach ($contents as $content => $value) {
|
387 |
-
//
|
388 |
-
// // Skip dots
|
389 |
-
// if ($content->isDot())
|
390 |
-
//
|
391 |
-
//
|
392 |
-
// // Get into the directory
|
393 |
-
// if (!$content->isLink() && $content->isDir()) {
|
394 |
-
// return $this->processDirectory($content->getRealPath());
|
395 |
-
// }
|
396 |
-
//
|
397 |
-
// // Delete file
|
398 |
-
// if ($content->isFile()) {
|
399 |
-
// @unlink($content->getRealPath());
|
400 |
-
// }
|
401 |
-
// }
|
402 |
-
//
|
403 |
-
// // Delete directory
|
404 |
-
// $this->job->lastDeletedDirectory = realpath($path . "/..");
|
405 |
-
// @rmdir($path);
|
406 |
-
// $this->updateJob();
|
407 |
-
// $this->processDirectory($this->job->nextDirectoryToDelete);
|
408 |
-
// }
|
409 |
-
|
410 |
-
/**
|
411 |
-
* @param string $path
|
412 |
-
* @return bool
|
413 |
-
*/
|
414 |
-
// private function shouldStop($path) {
|
415 |
-
// // Just to make sure the root dir is never deleted!
|
416 |
-
// if ($path === get_home_path()) {
|
417 |
-
// $this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
418 |
-
// return true;
|
419 |
-
// }
|
420 |
-
//
|
421 |
-
// // Check if threshold is reached and is valid dir
|
422 |
-
// return (
|
423 |
-
// $this->isOverThreshold() ||
|
424 |
-
// !is_dir($path) ||
|
425 |
-
// $this->isDirectoryDeletingFinished()
|
426 |
-
// );
|
427 |
-
// }
|
428 |
-
|
429 |
-
/**
|
430 |
-
*
|
431 |
-
* @return boolean
|
432 |
-
*/
|
433 |
-
public function isFatalError() {
|
434 |
-
if (rtrim($this->clone->path, "/") == rtrim(get_home_path(), "/")) {
|
435 |
-
return true;
|
436 |
-
}
|
437 |
-
return false;
|
438 |
-
}
|
439 |
-
|
440 |
-
/**
|
441 |
-
* Finish / Update Existing Clones
|
442 |
-
*/
|
443 |
-
public function deleteFinish() {
|
444 |
-
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
445 |
-
|
446 |
-
// Check if clones still exist
|
447 |
-
$this->log("Verifying existing clones...");
|
448 |
-
foreach ($existingClones as $name => $clone) {
|
449 |
-
if (!is_dir($clone["path"])) {
|
450 |
-
unset($existingClones[$name]);
|
451 |
-
}
|
452 |
-
}
|
453 |
-
$this->log("Existing clones verified!");
|
454 |
-
|
455 |
-
if (false === update_option("wpstg_existing_clones_beta", $existingClones)) {
|
456 |
-
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
457 |
-
}
|
458 |
-
|
459 |
-
// Delete cached file
|
460 |
-
$this->cache->delete("delete_job_{$this->clone->name}");
|
461 |
-
$this->cache->delete("delete_directories_{$this->clone->name}");
|
462 |
-
|
463 |
-
//return true;
|
464 |
-
$response = array('delete' => 'finished');
|
465 |
-
wp_die(json_encode($response));
|
466 |
-
}
|
467 |
-
|
468 |
-
/**
|
469 |
-
* Get json response
|
470 |
-
* return json
|
471 |
-
*/
|
472 |
-
// private function returnException($message = ''){
|
473 |
-
// wp_die( json_encode(array(
|
474 |
-
// 'job' => 'delete',
|
475 |
-
// 'status' => false,
|
476 |
-
// 'message' => $message,
|
477 |
-
// 'error' => true
|
478 |
-
// )));
|
479 |
-
// }
|
480 |
-
/**
|
481 |
-
* Get json response
|
482 |
-
* return json
|
483 |
-
*/
|
484 |
-
private function returnFinish($message = '') {
|
485 |
-
|
486 |
-
$this->deleteFinish();
|
487 |
-
|
488 |
-
wp_die(json_encode(array(
|
489 |
-
'job' => 'delete',
|
490 |
-
'status' => true,
|
491 |
-
'message' => $message,
|
492 |
-
'error' => false,
|
493 |
-
'delete' => 'finished'
|
494 |
-
)));
|
495 |
-
}
|
496 |
-
|
497 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
|
6 |
+
use WPStaging\Utils\Directories;
|
7 |
+
use WPStaging\Utils\Logger;
|
8 |
+
use WPStaging\WPStaging;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Delete
|
12 |
+
* @package WPStaging\Backend\Modules\Jobs
|
13 |
+
*/
|
14 |
+
class Delete extends Job {
|
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 |
+
*
|
38 |
+
* @var object
|
39 |
+
*/
|
40 |
+
public $wpdb;
|
41 |
+
|
42 |
+
public function __construct() {
|
43 |
+
parent::__construct();
|
44 |
+
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Sets Clone and Table Records
|
49 |
+
* @param null|array $clone
|
50 |
+
*/
|
51 |
+
public function setData($clone = null) {
|
52 |
+
if (!is_array($clone)) {
|
53 |
+
$this->getCloneRecords();
|
54 |
+
} else {
|
55 |
+
$this->clone = (object) $clone;
|
56 |
+
$this->forceDeleteDirectories = true;
|
57 |
+
}
|
58 |
+
|
59 |
+
$this->getTableRecords();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get clone
|
64 |
+
* @param null|string $name
|
65 |
+
* @throws CloneNotFoundException
|
66 |
+
*/
|
67 |
+
private function getCloneRecords($name = null) {
|
68 |
+
if (null === $name && !isset($_POST["clone"])) {
|
69 |
+
$this->log("Clone name is not set", Logger::TYPE_FATAL);
|
70 |
+
throw new CloneNotFoundException();
|
71 |
+
}
|
72 |
+
|
73 |
+
if (null === $name) {
|
74 |
+
$name = $_POST["clone"];
|
75 |
+
}
|
76 |
+
|
77 |
+
$clones = get_option("wpstg_existing_clones_beta", array());
|
78 |
+
|
79 |
+
if (empty($clones) || !isset($clones[$name])) {
|
80 |
+
$this->log("Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL);
|
81 |
+
throw new CloneNotFoundException();
|
82 |
+
}
|
83 |
+
|
84 |
+
$this->clone = $clones[$name];
|
85 |
+
$this->clone["name"] = $name;
|
86 |
+
|
87 |
+
$this->clone = (object) $this->clone;
|
88 |
+
|
89 |
+
unset($clones);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get Tables
|
94 |
+
*/
|
95 |
+
private function getTableRecords() {
|
96 |
+
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
97 |
+
$this->wpdb = WPStaging::getInstance()->get("wpdb");
|
98 |
+
|
99 |
+
$stagingPrefix = $this->getStagingPrefix();
|
100 |
+
|
101 |
+
$tables = $this->wpdb->get_results("SHOW TABLE STATUS LIKE '{$stagingPrefix}%'");
|
102 |
+
|
103 |
+
$this->tables = array();
|
104 |
+
|
105 |
+
foreach ($tables as $table) {
|
106 |
+
$this->tables[] = array(
|
107 |
+
"name" => $table->Name,
|
108 |
+
"size" => $this->formatSize(($table->Data_length + $table->Index_length))
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
$this->tables = json_decode(json_encode($this->tables));
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Check and return prefix of the staging site
|
117 |
+
*/
|
118 |
+
public function getStagingPrefix() {
|
119 |
+
// Prefix not defined! Happens if staging site has ben generated with older version of wpstg
|
120 |
+
// Try to get staging prefix from wp-config.php of staging site
|
121 |
+
if (empty($this->clone->prefix)) {
|
122 |
+
// Throw error
|
123 |
+
$path = ABSPATH . $this->clone->directoryName . "/wp-config.php";
|
124 |
+
if (false === ($content = @file_get_contents($path))) {
|
125 |
+
$this->log("Can not open {$path}. Can't read contents", Logger::TYPE_ERROR);
|
126 |
+
// Create a random prefix which hopefully never exists.
|
127 |
+
$this->clone->prefix = rand(7, 15) . '_';
|
128 |
+
} else {
|
129 |
+
|
130 |
+
// Get prefix from wp-config.php
|
131 |
+
//preg_match_all("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
132 |
+
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
133 |
+
//wp_die(var_dump($matches));
|
134 |
+
|
135 |
+
if (!empty($matches[1])) {
|
136 |
+
$this->clone->prefix = $matches[1];
|
137 |
+
} else {
|
138 |
+
$this->log("Fatal Error: Can not delete staging site. Can not find Prefix. '{$matches[1]}'. Stopping for security reasons. Creating a new staging site will likely resolve this the next time. Contact support@wp-staging.com");
|
139 |
+
// Create a random prefix which hopefully never exists.
|
140 |
+
return $this->clone->prefix = rand(7, 15) . '_';
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
// Check if staging prefix is the same as the live prefix
|
146 |
+
if ($this->wpdb->prefix == $this->clone->prefix) {
|
147 |
+
$this->log("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
148 |
+
wp_die("Fatal Error: Can not delete staging site. Prefix. '{$this->clone->prefix}' is used for the live site. Creating a new staging site will likely resolve this the next time. Stopping for security reasons. Contact support@wp-staging.com");
|
149 |
+
}
|
150 |
+
|
151 |
+
// Else
|
152 |
+
return $this->clone->prefix;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Format bytes into human readable form
|
157 |
+
* @param int $bytes
|
158 |
+
* @param int $precision
|
159 |
+
* @return string
|
160 |
+
*/
|
161 |
+
public function formatSize($bytes, $precision = 2) {
|
162 |
+
if ((int) $bytes < 1) {
|
163 |
+
return '';
|
164 |
+
}
|
165 |
+
|
166 |
+
$units = array('B', "KB", "MB", "GB", "TB");
|
167 |
+
|
168 |
+
$bytes = (int) $bytes;
|
169 |
+
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
170 |
+
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
171 |
+
|
172 |
+
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* @return false
|
177 |
+
*/
|
178 |
+
public function getClone() {
|
179 |
+
return $this->clone;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* @return null|object
|
184 |
+
*/
|
185 |
+
public function getTables() {
|
186 |
+
return $this->tables;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Start Module
|
191 |
+
* @param null|array $clone
|
192 |
+
* @return bool
|
193 |
+
*/
|
194 |
+
public function start($clone = null) {
|
195 |
+
// Set data
|
196 |
+
$this->setData($clone);
|
197 |
+
|
198 |
+
// Get the job first
|
199 |
+
$this->getJob();
|
200 |
+
|
201 |
+
$method = "delete" . ucwords($this->job->current);
|
202 |
+
return $this->{$method}();
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Get job data
|
207 |
+
*/
|
208 |
+
private function getJob() {
|
209 |
+
$this->job = $this->cache->get("delete_job_{$this->clone->name}");
|
210 |
+
|
211 |
+
|
212 |
+
if (null !== $this->job) {
|
213 |
+
return;
|
214 |
+
}
|
215 |
+
|
216 |
+
// Generate JOB
|
217 |
+
$this->job = (object) array(
|
218 |
+
"current" => "tables",
|
219 |
+
"nextDirectoryToDelete" => $this->clone->path,
|
220 |
+
"name" => $this->clone->name
|
221 |
+
);
|
222 |
+
|
223 |
+
$this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* @return bool
|
228 |
+
*/
|
229 |
+
private function updateJob() {
|
230 |
+
$this->job->nextDirectoryToDelete = trim($this->job->nextDirectoryToDelete);
|
231 |
+
return $this->cache->save("delete_job_{$this->clone->name}", $this->job);
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @return array
|
236 |
+
*/
|
237 |
+
private function getTablesToRemove() {
|
238 |
+
$tables = $this->getTableNames();
|
239 |
+
|
240 |
+
if (!isset($_POST["excludedTables"]) || !is_array($_POST["excludedTables"]) || empty($_POST["excludedTables"])) {
|
241 |
+
return $tables;
|
242 |
+
}
|
243 |
+
|
244 |
+
return array_diff($tables, $_POST["excludedTables"]);
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* @return array
|
249 |
+
*/
|
250 |
+
private function getTableNames() {
|
251 |
+
return (!is_array($this->tables)) ? array() : array_map(function($value) {
|
252 |
+
return ($value->name);
|
253 |
+
}, $this->tables);
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Delete Tables
|
258 |
+
*/
|
259 |
+
public function deleteTables() {
|
260 |
+
if ($this->isOverThreshold()) {
|
261 |
+
return;
|
262 |
+
}
|
263 |
+
|
264 |
+
//$wpdb = WPStaging::getInstance()->get("wpdb");
|
265 |
+
|
266 |
+
foreach ($this->getTablesToRemove() as $table) {
|
267 |
+
// PROTECTION: Never delete any table that beginns with wp prefix of live site
|
268 |
+
if ($this->startsWith($table, $this->wpdb->prefix)) {
|
269 |
+
$this->log("Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL);
|
270 |
+
return false;
|
271 |
+
} else {
|
272 |
+
$this->wpdb->query("DROP TABLE {$table}");
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
// Move on to the next
|
277 |
+
$this->job->current = "directory";
|
278 |
+
$this->updateJob();
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Check if a strings start with a specific string
|
283 |
+
* @param string $haystack
|
284 |
+
* @param string $needle
|
285 |
+
* @return bool
|
286 |
+
*/
|
287 |
+
protected function startsWith($haystack, $needle) {
|
288 |
+
$length = strlen($needle);
|
289 |
+
return (substr($haystack, 0, $length) === $needle);
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Delete complete directory including all files and subfolders
|
294 |
+
*
|
295 |
+
* @throws InvalidArgumentException
|
296 |
+
*/
|
297 |
+
public function deleteDirectory() {
|
298 |
+
if ($this->isFatalError()) {
|
299 |
+
$this->returnException('Can not delete directory: ' . $this->clone->path . '. This seems to be the root directory. Please contact support@wp-staging.com');
|
300 |
+
throw new \Exception('Can not delete directory: ' . $this->clone->path . ' This seems to be the root directory. Please contact support@wp-staging.com');
|
301 |
+
}
|
302 |
+
// Finished or path does not exist
|
303 |
+
if (
|
304 |
+
empty($this->clone->path) ||
|
305 |
+
$this->clone->path == get_home_path() ||
|
306 |
+
!is_dir($this->clone->path)) {
|
307 |
+
|
308 |
+
$this->job->current = "finish";
|
309 |
+
$this->updateJob();
|
310 |
+
return $this->returnFinish();
|
311 |
+
}
|
312 |
+
|
313 |
+
$this->log("Delete staging site: " . $this->clone->path, Logger::TYPE_INFO);
|
314 |
+
|
315 |
+
// Just to make sure the root dir is never deleted!
|
316 |
+
if ($this->clone->path == get_home_path()) {
|
317 |
+
$this->log("Fatal Error 8: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
318 |
+
$this->returnException('Fatal Error 8: Trying to delete root of WP installation!');
|
319 |
+
}
|
320 |
+
|
321 |
+
// Check if threshold is reached
|
322 |
+
if ($this->isOverThreshold()) {
|
323 |
+
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
324 |
+
return;
|
325 |
+
}
|
326 |
+
|
327 |
+
$di = new \RecursiveDirectoryIterator($this->clone->path, \FilesystemIterator::SKIP_DOTS);
|
328 |
+
$ri = new \RecursiveIteratorIterator($di, \RecursiveIteratorIterator::CHILD_FIRST);
|
329 |
+
foreach ($ri as $file) {
|
330 |
+
//$file->isDir() ? @rmdir($file) : unlink($file);
|
331 |
+
$this->deleteFile($file);
|
332 |
+
if ($this->isOverThreshold()) {
|
333 |
+
//$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
|
334 |
+
return;
|
335 |
+
}
|
336 |
+
}
|
337 |
+
|
338 |
+
if (@rmdir($this->clone->path)) {
|
339 |
+
return $this->returnFinish();
|
340 |
+
}
|
341 |
+
return;
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Delete file
|
346 |
+
* @param object iterator $file
|
347 |
+
*/
|
348 |
+
private function deleteFile($file) {
|
349 |
+
if ($file->isDir()) {
|
350 |
+
if (!@rmdir($file)) {
|
351 |
+
$this->returnException('Permission Error: Can not delete folder ' . $file);
|
352 |
+
}
|
353 |
+
} else {
|
354 |
+
if (!unlink($file)) {
|
355 |
+
$this->returnException('Permission Error: Can not delete file ' . $file);
|
356 |
+
}
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* @return bool
|
362 |
+
*/
|
363 |
+
public function isDirectoryDeletingFinished() {
|
364 |
+
return (
|
365 |
+
(false === $this->forceDeleteDirectories && (!isset($_POST["deleteDir"]) || '1' !== $_POST["deleteDir"])) ||
|
366 |
+
!is_dir($this->clone->path) || ABSPATH === $this->job->nextDirectoryToDelete
|
367 |
+
);
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Delete contents of the directory if there are no directories in it and then delete itself
|
372 |
+
* @param string $path
|
373 |
+
* @return mixed
|
374 |
+
*/
|
375 |
+
// private function processDirectory($path) {
|
376 |
+
// // We hit the limit, stop
|
377 |
+
// if ($this->shouldStop($path)) {
|
378 |
+
// $this->updateJob();
|
379 |
+
// return false;
|
380 |
+
// }
|
381 |
+
//
|
382 |
+
// $this->totalRecursion++;
|
383 |
+
//
|
384 |
+
// $contents = new \DirectoryIterator($path);
|
385 |
+
//
|
386 |
+
// foreach ($contents as $content => $value) {
|
387 |
+
//
|
388 |
+
// // Skip dots
|
389 |
+
// if ($content->isDot())
|
390 |
+
//
|
391 |
+
//
|
392 |
+
// // Get into the directory
|
393 |
+
// if (!$content->isLink() && $content->isDir()) {
|
394 |
+
// return $this->processDirectory($content->getRealPath());
|
395 |
+
// }
|
396 |
+
//
|
397 |
+
// // Delete file
|
398 |
+
// if ($content->isFile()) {
|
399 |
+
// @unlink($content->getRealPath());
|
400 |
+
// }
|
401 |
+
// }
|
402 |
+
//
|
403 |
+
// // Delete directory
|
404 |
+
// $this->job->lastDeletedDirectory = realpath($path . "/..");
|
405 |
+
// @rmdir($path);
|
406 |
+
// $this->updateJob();
|
407 |
+
// $this->processDirectory($this->job->nextDirectoryToDelete);
|
408 |
+
// }
|
409 |
+
|
410 |
+
/**
|
411 |
+
* @param string $path
|
412 |
+
* @return bool
|
413 |
+
*/
|
414 |
+
// private function shouldStop($path) {
|
415 |
+
// // Just to make sure the root dir is never deleted!
|
416 |
+
// if ($path === get_home_path()) {
|
417 |
+
// $this->log("Fatal Error: Trying to delete root of WP installation!", Logger::TYPE_CRITICAL);
|
418 |
+
// return true;
|
419 |
+
// }
|
420 |
+
//
|
421 |
+
// // Check if threshold is reached and is valid dir
|
422 |
+
// return (
|
423 |
+
// $this->isOverThreshold() ||
|
424 |
+
// !is_dir($path) ||
|
425 |
+
// $this->isDirectoryDeletingFinished()
|
426 |
+
// );
|
427 |
+
// }
|
428 |
+
|
429 |
+
/**
|
430 |
+
*
|
431 |
+
* @return boolean
|
432 |
+
*/
|
433 |
+
public function isFatalError() {
|
434 |
+
if (rtrim($this->clone->path, "/") == rtrim(get_home_path(), "/")) {
|
435 |
+
return true;
|
436 |
+
}
|
437 |
+
return false;
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Finish / Update Existing Clones
|
442 |
+
*/
|
443 |
+
public function deleteFinish() {
|
444 |
+
$existingClones = get_option("wpstg_existing_clones_beta", array());
|
445 |
+
|
446 |
+
// Check if clones still exist
|
447 |
+
$this->log("Verifying existing clones...");
|
448 |
+
foreach ($existingClones as $name => $clone) {
|
449 |
+
if (!is_dir($clone["path"])) {
|
450 |
+
unset($existingClones[$name]);
|
451 |
+
}
|
452 |
+
}
|
453 |
+
$this->log("Existing clones verified!");
|
454 |
+
|
455 |
+
if (false === update_option("wpstg_existing_clones_beta", $existingClones)) {
|
456 |
+
$this->log("Failed to save {$this->options->clone}'s clone job data to database'");
|
457 |
+
}
|
458 |
+
|
459 |
+
// Delete cached file
|
460 |
+
$this->cache->delete("delete_job_{$this->clone->name}");
|
461 |
+
$this->cache->delete("delete_directories_{$this->clone->name}");
|
462 |
+
|
463 |
+
//return true;
|
464 |
+
$response = array('delete' => 'finished');
|
465 |
+
wp_die(json_encode($response));
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* Get json response
|
470 |
+
* return json
|
471 |
+
*/
|
472 |
+
// private function returnException($message = ''){
|
473 |
+
// wp_die( json_encode(array(
|
474 |
+
// 'job' => 'delete',
|
475 |
+
// 'status' => false,
|
476 |
+
// 'message' => $message,
|
477 |
+
// 'error' => true
|
478 |
+
// )));
|
479 |
+
// }
|
480 |
+
/**
|
481 |
+
* Get json response
|
482 |
+
* return json
|
483 |
+
*/
|
484 |
+
private function returnFinish($message = '') {
|
485 |
+
|
486 |
+
$this->deleteFinish();
|
487 |
+
|
488 |
+
wp_die(json_encode(array(
|
489 |
+
'job' => 'delete',
|
490 |
+
'status' => true,
|
491 |
+
'message' => $message,
|
492 |
+
'error' => false,
|
493 |
+
'delete' => 'finished'
|
494 |
+
)));
|
495 |
+
}
|
496 |
+
|
497 |
+
}
|
apps/Backend/Modules/Jobs/Directories.php
CHANGED
@@ -1,451 +1,428 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if (!defined("WPINC")) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Utils\Logger;
|
12 |
-
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
13 |
-
use WPStaging\Iterators\RecursiveFilterNewLine;
|
14 |
-
use WPStaging\Iterators\RecursiveFilterExclude;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Class Files
|
18 |
-
* @package WPStaging\Backend\Modules\Directories
|
19 |
-
*/
|
20 |
-
class Directories extends JobExecutable {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @var array
|
24 |
-
*/
|
25 |
-
private $files = array();
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Total steps to do
|
29 |
-
* @var int
|
30 |
-
*/
|
31 |
-
private $total = 4;
|
32 |
-
private $fileHandle;
|
33 |
-
|
34 |
-
private $filename;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Initialize
|
38 |
-
*/
|
39 |
-
public function initialize() {
|
40 |
-
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
45 |
-
* @return void
|
46 |
-
*/
|
47 |
-
protected function calculateTotalSteps() {
|
48 |
-
$this->options->totalSteps = $this->total;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Start Module
|
53 |
-
* @return object
|
54 |
-
*/
|
55 |
-
public function start() {
|
56 |
-
|
57 |
-
// Execute steps
|
58 |
-
$this->run();
|
59 |
-
|
60 |
-
// Save option, progress
|
61 |
-
$this->saveProgress();
|
62 |
-
|
63 |
-
return (object) $this->response;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Step 1
|
68 |
-
* Get WP Root files
|
69 |
-
*/
|
70 |
-
private function getWpRootFiles() {
|
71 |
-
|
72 |
-
//
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
}
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
*
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
*
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
}
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
$this->
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
//
|
371 |
-
|
372 |
-
//
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
// }
|
430 |
-
//
|
431 |
-
// return (false !== @file_put_contents($fileName, $files));
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Get files
|
436 |
-
* @return void
|
437 |
-
*/
|
438 |
-
protected function getFiles() {
|
439 |
-
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
440 |
-
|
441 |
-
if (false === ($this->files = @file_get_contents($fileName))) {
|
442 |
-
$this->files = array();
|
443 |
-
return;
|
444 |
-
}
|
445 |
-
|
446 |
-
$this->files = explode(PHP_EOL, $this->files);
|
447 |
-
}
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if (!defined("WPINC")) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Utils\Logger;
|
12 |
+
use WPStaging\Iterators\RecursiveDirectoryIterator;
|
13 |
+
use WPStaging\Iterators\RecursiveFilterNewLine;
|
14 |
+
use WPStaging\Iterators\RecursiveFilterExclude;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class Files
|
18 |
+
* @package WPStaging\Backend\Modules\Directories
|
19 |
+
*/
|
20 |
+
class Directories extends JobExecutable {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
private $files = array();
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Total steps to do
|
29 |
+
* @var int
|
30 |
+
*/
|
31 |
+
private $total = 4;
|
32 |
+
private $fileHandle;
|
33 |
+
|
34 |
+
private $filename;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Initialize
|
38 |
+
*/
|
39 |
+
public function initialize() {
|
40 |
+
$this->filename = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
45 |
+
* @return void
|
46 |
+
*/
|
47 |
+
protected function calculateTotalSteps() {
|
48 |
+
$this->options->totalSteps = $this->total;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Start Module
|
53 |
+
* @return object
|
54 |
+
*/
|
55 |
+
public function start() {
|
56 |
+
|
57 |
+
// Execute steps
|
58 |
+
$this->run();
|
59 |
+
|
60 |
+
// Save option, progress
|
61 |
+
$this->saveProgress();
|
62 |
+
|
63 |
+
return (object) $this->response;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Step 1
|
68 |
+
* Get WP Root files
|
69 |
+
*/
|
70 |
+
private function getWpRootFiles() {
|
71 |
+
|
72 |
+
// Skip it
|
73 |
+
// if ($this->isDirectoryExcluded(ABSPATH)){
|
74 |
+
// return true;
|
75 |
+
// }
|
76 |
+
|
77 |
+
// open file handle
|
78 |
+
$files = $this->open($this->filename, 'a');
|
79 |
+
|
80 |
+
|
81 |
+
try {
|
82 |
+
|
83 |
+
// Iterate over wp root directory
|
84 |
+
$iterator = new \DirectoryIterator(ABSPATH);
|
85 |
+
|
86 |
+
$this->log( "Scanning ".ABSPATH." for its sub-directories and files" );
|
87 |
+
|
88 |
+
// Write path line
|
89 |
+
foreach ($iterator as $item) {
|
90 |
+
if (!$item->isDot() && $item->isFile()) {
|
91 |
+
if ($this->write($files, $iterator->getFilename() . PHP_EOL)) {
|
92 |
+
$this->options->totalFiles++;
|
93 |
+
|
94 |
+
// Add current file size
|
95 |
+
$this->options->totalFileSize += $iterator->getSize();
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
} catch (\Exception $e) {
|
100 |
+
$this->returnException('Error: ' . $e->getMessage());
|
101 |
+
//throw new \Exception('Out of disk space.');
|
102 |
+
} catch (\Exception $e) {
|
103 |
+
// Skip bad file permissions
|
104 |
+
}
|
105 |
+
|
106 |
+
$this->close($files);
|
107 |
+
return true;
|
108 |
+
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Step 2
|
113 |
+
* Get WP Content Files
|
114 |
+
*/
|
115 |
+
public function getWpContentFiles() {
|
116 |
+
|
117 |
+
// Skip it
|
118 |
+
if ($this->isDirectoryExcluded(WP_CONTENT_DIR)){
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
// open file handle
|
122 |
+
$files = $this->open($this->filename, 'a');
|
123 |
+
|
124 |
+
$excludeWpContent = array(
|
125 |
+
'HUGE-FOLDER',
|
126 |
+
'cache',
|
127 |
+
'wps-hide-login',
|
128 |
+
'node_modules',
|
129 |
+
'nbproject'
|
130 |
+
);
|
131 |
+
|
132 |
+
try {
|
133 |
+
|
134 |
+
// Iterate over content directory
|
135 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator(WP_CONTENT_DIR);
|
136 |
+
|
137 |
+
// Exclude new line file names
|
138 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine($iterator);
|
139 |
+
|
140 |
+
// Exclude uploads, plugins or themes
|
141 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $excludeWpContent));
|
142 |
+
// Recursively iterate over content directory
|
143 |
+
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
144 |
+
|
145 |
+
$path = 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
|
146 |
+
$this->log( "Scanning {$path} for its sub-directories and files" );
|
147 |
+
|
148 |
+
// Write path line
|
149 |
+
foreach ($iterator as $item) {
|
150 |
+
if ($item->isFile()) {
|
151 |
+
if ($this->write($files, 'wp-content' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL)) {
|
152 |
+
$this->options->totalFiles++;
|
153 |
+
|
154 |
+
// Add current file size
|
155 |
+
$this->options->totalFileSize += $iterator->getSize();
|
156 |
+
}
|
157 |
+
}
|
158 |
+
}
|
159 |
+
} catch (\Exception $e) {
|
160 |
+
//$this->returnException('Out of disk space.');
|
161 |
+
throw new \Exception('Error: ' . $e->getMessage());
|
162 |
+
} catch (\Exception $e) {
|
163 |
+
// Skip bad file permissions
|
164 |
+
}
|
165 |
+
|
166 |
+
// close the file handler
|
167 |
+
$this->close($files);
|
168 |
+
return true;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Step 3
|
173 |
+
* @return boolean
|
174 |
+
* @throws \Exception
|
175 |
+
*/
|
176 |
+
public function getWpIncludesFiles() {
|
177 |
+
|
178 |
+
// Skip it
|
179 |
+
if ($this->isDirectoryExcluded(ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR)){
|
180 |
+
return true;
|
181 |
+
}
|
182 |
+
|
183 |
+
// open file handle and attach data to end of file
|
184 |
+
$files = $this->open($this->filename, 'a');
|
185 |
+
|
186 |
+
try {
|
187 |
+
|
188 |
+
// Iterate over wp-admin directory
|
189 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator(ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR);
|
190 |
+
|
191 |
+
// Exclude new line file names
|
192 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine($iterator);
|
193 |
+
|
194 |
+
// Exclude uploads, plugins or themes
|
195 |
+
//$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $exclude_filters));
|
196 |
+
// Recursively iterate over wp-includes directory
|
197 |
+
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
198 |
+
|
199 |
+
$path = ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR;
|
200 |
+
$this->log( "Scanning {$path} for its sub-directories and files" );
|
201 |
+
|
202 |
+
// Write files
|
203 |
+
foreach ($iterator as $item) {
|
204 |
+
if ($item->isFile()) {
|
205 |
+
if ($this->write($files, 'wp-includes' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL)) {
|
206 |
+
$this->options->totalFiles++;
|
207 |
+
|
208 |
+
// Add current file size
|
209 |
+
$this->options->totalFileSize += $iterator->getSize();
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
} catch (\Exception $e) {
|
214 |
+
//$this->returnException('Out of disk space.');
|
215 |
+
throw new \Exception('Error: ' . $e->getMessage());
|
216 |
+
} catch (\Exception $e) {
|
217 |
+
// Skip bad file permissions
|
218 |
+
}
|
219 |
+
|
220 |
+
// close the file handler
|
221 |
+
$this->close($files);
|
222 |
+
return true;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Step 4
|
227 |
+
* @return boolean
|
228 |
+
* @throws \Exception
|
229 |
+
*/
|
230 |
+
public function getWpAdminFiles() {
|
231 |
+
|
232 |
+
// Skip it
|
233 |
+
if ($this->isDirectoryExcluded(ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR)) {
|
234 |
+
return true;
|
235 |
+
}
|
236 |
+
|
237 |
+
// open file handle and attach data to end of file
|
238 |
+
$files = $this->open($this->filename, 'a');
|
239 |
+
|
240 |
+
try {
|
241 |
+
|
242 |
+
// Iterate over wp-admin directory
|
243 |
+
$iterator = new \WPStaging\Iterators\RecursiveDirectoryIterator(ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR);
|
244 |
+
|
245 |
+
// Exclude new line file names
|
246 |
+
$iterator = new \WPStaging\Iterators\RecursiveFilterNewLine($iterator);
|
247 |
+
|
248 |
+
// Exclude uploads, plugins or themes
|
249 |
+
//$iterator = new \WPStaging\Iterators\RecursiveFilterExclude($iterator, apply_filters('wpstg_exclude_content', $exclude_filters));
|
250 |
+
// Recursively iterate over content directory
|
251 |
+
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
252 |
+
|
253 |
+
$path = ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR;
|
254 |
+
$this->log("Scanning {$path} for its sub-directories and files");
|
255 |
+
|
256 |
+
// Write path line
|
257 |
+
foreach ($iterator as $item) {
|
258 |
+
if ($item->isFile()) {
|
259 |
+
if ($this->write($files, 'wp-admin' . DIRECTORY_SEPARATOR . $iterator->getSubPathName() . PHP_EOL)) {
|
260 |
+
$this->options->totalFiles++;
|
261 |
+
// Add current file size
|
262 |
+
$this->options->totalFileSize += $iterator->getSize();
|
263 |
+
}
|
264 |
+
}
|
265 |
+
}
|
266 |
+
} catch (\Exception $e) {
|
267 |
+
$this->returnException('Error: ' . $e->getMessage());
|
268 |
+
//throw new \Exception('Error: ' . $e->getMessage());
|
269 |
+
} catch (\Exception $e) {
|
270 |
+
// Skip bad file permissions
|
271 |
+
}
|
272 |
+
|
273 |
+
// close the file handler
|
274 |
+
$this->close($files);
|
275 |
+
return true;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Closes a file handle
|
280 |
+
*
|
281 |
+
* @param resource $handle File handle to close
|
282 |
+
* @return boolean
|
283 |
+
*/
|
284 |
+
public function close($handle) {
|
285 |
+
return @fclose($handle);
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Opens a file in specified mode
|
290 |
+
*
|
291 |
+
* @param string $file Path to the file to open
|
292 |
+
* @param string $mode Mode in which to open the file
|
293 |
+
* @return resource
|
294 |
+
* @throws Exception
|
295 |
+
*/
|
296 |
+
public function open($file, $mode) {
|
297 |
+
|
298 |
+
$file_handle = @fopen($file, $mode);
|
299 |
+
if (false === $file_handle) {
|
300 |
+
$this->returnException(sprintf(__('Unable to open %s with mode %s', 'wpstg'), $file, $mode));
|
301 |
+
//throw new Exception(sprintf(__('Unable to open %s with mode %s', 'wpstg'), $file, $mode));
|
302 |
+
}
|
303 |
+
|
304 |
+
return $file_handle;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Write contents to a file
|
309 |
+
*
|
310 |
+
* @param resource $handle File handle to write to
|
311 |
+
* @param string $content Contents to write to the file
|
312 |
+
* @return integer
|
313 |
+
* @throws Exception
|
314 |
+
* @throws Exception
|
315 |
+
*/
|
316 |
+
public function write($handle, $content) {
|
317 |
+
$write_result = @fwrite($handle, $content);
|
318 |
+
if (false === $write_result) {
|
319 |
+
if (( $meta = \stream_get_meta_data($handle))) {
|
320 |
+
//$this->returnException(sprintf(__('Unable to write to: %s', 'wpstg'), $meta['uri']));
|
321 |
+
throw new \Exception(sprintf(__('Unable to write to: %s', 'wpstg'), $meta['uri']));
|
322 |
+
}
|
323 |
+
} elseif (strlen($content) !== $write_result) {
|
324 |
+
//$this->returnException(__('Out of disk space.', 'wpstg'));
|
325 |
+
throw new \Exception(__('Out of disk space.', 'wpstg'));
|
326 |
+
}
|
327 |
+
|
328 |
+
return $write_result;
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Execute the Current Step
|
333 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
334 |
+
* @return bool
|
335 |
+
*/
|
336 |
+
protected function execute() {
|
337 |
+
|
338 |
+
// No job left to execute
|
339 |
+
if ($this->isFinished()) {
|
340 |
+
$this->prepareResponse(true, false);
|
341 |
+
return false;
|
342 |
+
}
|
343 |
+
|
344 |
+
|
345 |
+
if ($this->options->currentStep == 0) {
|
346 |
+
$this->getWpRootFiles();
|
347 |
+
$this->prepareResponse(false, true);
|
348 |
+
return false;
|
349 |
+
}
|
350 |
+
|
351 |
+
if ($this->options->currentStep == 1) {
|
352 |
+
$this->getWpContentFiles();
|
353 |
+
$this->prepareResponse(false, true);
|
354 |
+
return false;
|
355 |
+
}
|
356 |
+
|
357 |
+
if ($this->options->currentStep == 2) {
|
358 |
+
$this->getWpIncludesFiles();
|
359 |
+
$this->prepareResponse(false, true);
|
360 |
+
return false;
|
361 |
+
}
|
362 |
+
|
363 |
+
if ($this->options->currentStep == 3) {
|
364 |
+
$this->getWpAdminFiles();
|
365 |
+
$this->prepareResponse(false, true);
|
366 |
+
return false;
|
367 |
+
}
|
368 |
+
|
369 |
+
|
370 |
+
// Prepare response
|
371 |
+
$this->prepareResponse(false, true);
|
372 |
+
// Not finished
|
373 |
+
return true;
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Checks Whether There is Any Job to Execute or Not
|
378 |
+
* @return bool
|
379 |
+
*/
|
380 |
+
protected function isFinished() {
|
381 |
+
return (
|
382 |
+
$this->options->currentStep > $this->total ||
|
383 |
+
$this->options->currentStep == 4
|
384 |
+
);
|
385 |
+
}
|
386 |
+
|
387 |
+
|
388 |
+
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Save files
|
392 |
+
* @return bool
|
393 |
+
*/
|
394 |
+
protected function saveProgress() {
|
395 |
+
return $this->saveOptions();
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Get files
|
400 |
+
* @return void
|
401 |
+
*/
|
402 |
+
protected function getFiles() {
|
403 |
+
$fileName = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
404 |
+
|
405 |
+
if (false === ($this->files = @file_get_contents($fileName))) {
|
406 |
+
$this->files = array();
|
407 |
+
return;
|
408 |
+
}
|
409 |
+
|
410 |
+
$this->files = explode(PHP_EOL, $this->files);
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Check if directory is excluded from colec
|
415 |
+
* @param string $directory
|
416 |
+
* @return bool
|
417 |
+
*/
|
418 |
+
protected function isDirectoryExcluded($directory) {
|
419 |
+
foreach ($this->options->excludedDirectories as $excludedDirectory) {
|
420 |
+
if (strpos($directory, $excludedDirectory) === 0) {
|
421 |
+
return true;
|
422 |
+
}
|
423 |
+
}
|
424 |
+
|
425 |
+
return false;
|
426 |
+
}
|
427 |
+
|
428 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apps/Backend/Modules/Jobs/Files.php
CHANGED
@@ -1,365 +1,366 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
|
8 |
-
if (!defined("WPINC")) {
|
9 |
-
die;
|
10 |
-
}
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Class Files
|
14 |
-
* @package WPStaging\Backend\Modules\Jobs
|
15 |
-
*/
|
16 |
-
class Files extends JobExecutable {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @var \SplFileObject
|
20 |
-
*/
|
21 |
-
private $file;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @var int
|
25 |
-
*/
|
26 |
-
private $maxFilesPerRun;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* File Object
|
30 |
-
*/
|
31 |
-
//private $verifyFiles = array();
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @var string
|
35 |
-
*/
|
36 |
-
private $destination;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Initialization
|
40 |
-
*/
|
41 |
-
public function initialize() {
|
42 |
-
|
43 |
-
$this->destination = ABSPATH . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
44 |
-
|
45 |
-
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
46 |
-
|
47 |
-
if (is_file($filePath)) {
|
48 |
-
$this->file = new \SplFileObject($filePath, 'r');
|
49 |
-
}
|
50 |
-
|
51 |
-
// Informational logs
|
52 |
-
if (0 == $this->options->currentStep) {
|
53 |
-
$this->log("Copying files...");
|
54 |
-
}
|
55 |
-
|
56 |
-
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
57 |
-
$this->maxFilesPerRun = $this->settings->fileLimit;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
62 |
-
* @return void
|
63 |
-
*/
|
64 |
-
protected function calculateTotalSteps() {
|
65 |
-
$this->options->totalSteps = ceil($this->options->totalFiles / $this->maxFilesPerRun);
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Execute the Current Step
|
70 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
71 |
-
* @return bool
|
72 |
-
*/
|
73 |
-
protected function execute() {
|
74 |
-
// Finished
|
75 |
-
if ($this->isFinished()) {
|
76 |
-
$this->log("Copying files finished");
|
77 |
-
$this->prepareResponse(true, false);
|
78 |
-
return false;
|
79 |
-
}
|
80 |
-
|
81 |
-
// Get files and copy'em
|
82 |
-
if (!$this->getFilesAndCopy()) {
|
83 |
-
$this->prepareResponse(false, false);
|
84 |
-
return false;
|
85 |
-
}
|
86 |
-
|
87 |
-
// Prepare and return response
|
88 |
-
$this->prepareResponse();
|
89 |
-
|
90 |
-
// Not finished
|
91 |
-
return true;
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Get files and copy
|
96 |
-
* @return bool
|
97 |
-
*/
|
98 |
-
private function getFilesAndCopy() {
|
99 |
-
// Over limits threshold
|
100 |
-
if ($this->isOverThreshold()) {
|
101 |
-
// Prepare response and save current progress
|
102 |
-
$this->prepareResponse(false, false);
|
103 |
-
$this->saveOptions();
|
104 |
-
return false;
|
105 |
-
}
|
106 |
-
|
107 |
-
// Go to last copied line and than to next one
|
108 |
-
//if ($this->options->copiedFiles != 0) {
|
109 |
-
if (isset($this->options->copiedFiles) && $this->options->copiedFiles != 0) {
|
110 |
-
$this->file->seek($this->options->copiedFiles - 1);
|
111 |
-
}
|
112 |
-
|
113 |
-
$this->file->setFlags(\SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD);
|
114 |
-
|
115 |
-
|
116 |
-
// Loop x files at a time
|
117 |
-
for ($i = 0; $i < $this->maxFilesPerRun; $i++) {
|
118 |
-
|
119 |
-
// Increment copied files
|
120 |
-
// Do this anytime to make sure to not stuck in the same step / files
|
121 |
-
$this->options->copiedFiles++;
|
122 |
-
|
123 |
-
// End of file
|
124 |
-
if ($this->file->eof()) {
|
125 |
-
break;
|
126 |
-
}
|
127 |
-
|
128 |
-
|
129 |
-
$file = $this->file->fgets();
|
130 |
-
$this->debugLog('copy file ' . $file, Logger::TYPE_DEBUG);
|
131 |
-
$this->copyFile($file);
|
132 |
-
}
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
$this->
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
$
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
*
|
216 |
-
*
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
$
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
*
|
235 |
-
* @
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
//
|
240 |
-
//
|
241 |
-
//
|
242 |
-
//
|
243 |
-
//
|
244 |
-
//
|
245 |
-
//
|
246 |
-
//
|
247 |
-
//
|
248 |
-
//
|
249 |
-
//
|
250 |
-
//
|
251 |
-
//
|
252 |
-
//
|
253 |
-
//
|
254 |
-
//
|
255 |
-
//
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
*
|
261 |
-
* @
|
262 |
-
*
|
263 |
-
* @
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
//
|
268 |
-
//
|
269 |
-
// $
|
270 |
-
//
|
271 |
-
// $
|
272 |
-
//
|
273 |
-
//
|
274 |
-
//
|
275 |
-
//
|
276 |
-
//
|
277 |
-
//
|
278 |
-
//
|
279 |
-
//
|
280 |
-
//
|
281 |
-
//
|
282 |
-
//
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
*
|
288 |
-
* @param
|
289 |
-
* @
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
*
|
322 |
-
*
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
*
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
*
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
}
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
use WPStaging\Utils\Logger;
|
7 |
+
|
8 |
+
if (!defined("WPINC")) {
|
9 |
+
die;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class Files
|
14 |
+
* @package WPStaging\Backend\Modules\Jobs
|
15 |
+
*/
|
16 |
+
class Files extends JobExecutable {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var \SplFileObject
|
20 |
+
*/
|
21 |
+
private $file;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var int
|
25 |
+
*/
|
26 |
+
private $maxFilesPerRun;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* File Object
|
30 |
+
*/
|
31 |
+
//private $verifyFiles = array();
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
private $destination;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Initialization
|
40 |
+
*/
|
41 |
+
public function initialize() {
|
42 |
+
|
43 |
+
$this->destination = ABSPATH . $this->options->cloneDirectoryName . DIRECTORY_SEPARATOR;
|
44 |
+
|
45 |
+
$filePath = $this->cache->getCacheDir() . "files_to_copy." . $this->cache->getCacheExtension();
|
46 |
+
|
47 |
+
if (is_file($filePath)) {
|
48 |
+
$this->file = new \SplFileObject($filePath, 'r');
|
49 |
+
}
|
50 |
+
|
51 |
+
// Informational logs
|
52 |
+
if (0 == $this->options->currentStep) {
|
53 |
+
$this->log("Copying files...");
|
54 |
+
}
|
55 |
+
|
56 |
+
$this->settings->batchSize = $this->settings->batchSize * 1000000;
|
57 |
+
$this->maxFilesPerRun = $this->settings->fileLimit;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
protected function calculateTotalSteps() {
|
65 |
+
$this->options->totalSteps = ceil($this->options->totalFiles / $this->maxFilesPerRun);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Execute the Current Step
|
70 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
+
protected function execute() {
|
74 |
+
// Finished
|
75 |
+
if ($this->isFinished()) {
|
76 |
+
$this->log("Copying files finished");
|
77 |
+
$this->prepareResponse(true, false);
|
78 |
+
return false;
|
79 |
+
}
|
80 |
+
|
81 |
+
// Get files and copy'em
|
82 |
+
if (!$this->getFilesAndCopy()) {
|
83 |
+
$this->prepareResponse(false, false);
|
84 |
+
return false;
|
85 |
+
}
|
86 |
+
|
87 |
+
// Prepare and return response
|
88 |
+
$this->prepareResponse();
|
89 |
+
|
90 |
+
// Not finished
|
91 |
+
return true;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Get files and copy
|
96 |
+
* @return bool
|
97 |
+
*/
|
98 |
+
private function getFilesAndCopy() {
|
99 |
+
// Over limits threshold
|
100 |
+
if ($this->isOverThreshold()) {
|
101 |
+
// Prepare response and save current progress
|
102 |
+
$this->prepareResponse(false, false);
|
103 |
+
$this->saveOptions();
|
104 |
+
return false;
|
105 |
+
}
|
106 |
+
|
107 |
+
// Go to last copied line and than to next one
|
108 |
+
//if ($this->options->copiedFiles != 0) {
|
109 |
+
if (isset($this->options->copiedFiles) && $this->options->copiedFiles != 0) {
|
110 |
+
$this->file->seek($this->options->copiedFiles - 1);
|
111 |
+
}
|
112 |
+
|
113 |
+
$this->file->setFlags(\SplFileObject::SKIP_EMPTY | \SplFileObject::READ_AHEAD);
|
114 |
+
|
115 |
+
|
116 |
+
// Loop x files at a time
|
117 |
+
for ($i = 0; $i < $this->maxFilesPerRun; $i++) {
|
118 |
+
|
119 |
+
// Increment copied files
|
120 |
+
// Do this anytime to make sure to not stuck in the same step / files
|
121 |
+
$this->options->copiedFiles++;
|
122 |
+
|
123 |
+
// End of file
|
124 |
+
if ($this->file->eof()) {
|
125 |
+
break;
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
$file = $this->file->fgets();
|
130 |
+
$this->debugLog('copy file ' . $file, Logger::TYPE_DEBUG);
|
131 |
+
$this->copyFile($file);
|
132 |
+
}
|
133 |
+
|
134 |
+
$totalFiles = $this->options->copiedFiles;
|
135 |
+
// Log this only every 50 entries to keep the log small and to not block the rendering browser
|
136 |
+
if ($this->options->copiedFiles %50 == 0){
|
137 |
+
$this->log("Total {$totalFiles} files processed");
|
138 |
+
}
|
139 |
+
|
140 |
+
return true;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Checks Whether There is Any Job to Execute or Not
|
145 |
+
* @return bool
|
146 |
+
*/
|
147 |
+
private function isFinished() {
|
148 |
+
return (
|
149 |
+
$this->options->currentStep > $this->options->totalSteps ||
|
150 |
+
$this->options->copiedFiles >= $this->options->totalFiles
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* @param string $file
|
156 |
+
* @return bool
|
157 |
+
*/
|
158 |
+
private function copyFile($file) {
|
159 |
+
$file = trim(ABSPATH . $file);
|
160 |
+
|
161 |
+
$directory = dirname($file);
|
162 |
+
|
163 |
+
// Get file size
|
164 |
+
$fileSize = filesize($file);
|
165 |
+
|
166 |
+
// Directory is excluded
|
167 |
+
if ($this->isDirectoryExcluded($directory)) {
|
168 |
+
$this->debugLog("Skipping directory by rule: {$file}", Logger::TYPE_INFO);
|
169 |
+
return false;
|
170 |
+
}
|
171 |
+
|
172 |
+
// File is excluded
|
173 |
+
if ($this->isFileExcluded($file)) {
|
174 |
+
$this->log("Skipping file by rule: {$file}", Logger::TYPE_INFO);
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
|
178 |
+
// File is over maximum allowed file size (8MB)
|
179 |
+
if ($fileSize >= 8000000) {
|
180 |
+
$this->log("Skipping big file: {$file}", Logger::TYPE_INFO);
|
181 |
+
return false;
|
182 |
+
}
|
183 |
+
|
184 |
+
// Invalid file, skipping it as if succeeded
|
185 |
+
if (!is_file($file) || !is_readable($file)) {
|
186 |
+
$this->log("Can't read file or file doesn't exist {$file}");
|
187 |
+
return true;
|
188 |
+
}
|
189 |
+
|
190 |
+
// Failed to get destination
|
191 |
+
if (false === ($destination = $this->getDestination($file))) {
|
192 |
+
$this->log("Can't get the destination of {$file}");
|
193 |
+
return false;
|
194 |
+
}
|
195 |
+
|
196 |
+
// File is over batch size
|
197 |
+
if ($fileSize >= $this->settings->batchSize) {
|
198 |
+
$this->log("Trying to copy big file: {$file} -> {$destination}", Logger::TYPE_INFO);
|
199 |
+
return $this->copyBig($file, $destination, $this->settings->batchSize);
|
200 |
+
}
|
201 |
+
|
202 |
+
// Attempt to copy
|
203 |
+
if (!@copy($file, $destination)) {
|
204 |
+
$this->log("Failed to copy file to destination: {$file} -> {$destination}", Logger::TYPE_ERROR);
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
|
208 |
+
return true;
|
209 |
+
|
210 |
+
// Good old PHP
|
211 |
+
//return $this->copy($file, $destination);
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Gets destination file and checks if the directory exists, if it does not attempts to create it.
|
216 |
+
* If creating destination directory fails, it returns false, gives destination full path otherwise
|
217 |
+
* @param string $file
|
218 |
+
* @return bool|string
|
219 |
+
*/
|
220 |
+
private function getDestination($file) {
|
221 |
+
$relativePath = str_replace(ABSPATH, null, $file);
|
222 |
+
$destinationPath = $this->destination . $relativePath;
|
223 |
+
$destinationDirectory = dirname($destinationPath);
|
224 |
+
|
225 |
+
if (!is_dir($destinationDirectory) && !@mkdir($destinationDirectory, 0775, true)) {
|
226 |
+
$this->log("Files: Can not create directory {$destinationDirectory}", Logger::TYPE_ERROR);
|
227 |
+
return false;
|
228 |
+
}
|
229 |
+
|
230 |
+
return $destinationPath;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Copy File using PHP
|
235 |
+
* @param string $file
|
236 |
+
* @param string $destination
|
237 |
+
* @return bool
|
238 |
+
*/
|
239 |
+
// private function copy($file, $destination) {
|
240 |
+
// // Get file size
|
241 |
+
// $fileSize = filesize($file);
|
242 |
+
//
|
243 |
+
//
|
244 |
+
// // File is over batch size
|
245 |
+
// if ($fileSize >= $this->settings->batchSize) {
|
246 |
+
// $this->log("Trying to copy big file: {$file} -> {$destination}", Logger::TYPE_INFO);
|
247 |
+
// return $this->copyBig($file, $destination, $this->settings->batchSize);
|
248 |
+
// }
|
249 |
+
//
|
250 |
+
// // Attempt to copy
|
251 |
+
// if (!@copy($file, $destination)) {
|
252 |
+
// $this->log("Failed to copy file to destination: {$file} -> {$destination}", Logger::TYPE_ERROR);
|
253 |
+
// return false;
|
254 |
+
// }
|
255 |
+
//
|
256 |
+
// return true;
|
257 |
+
// }
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Copy bigger files than $this->settings->batchSize
|
261 |
+
* @param string $file
|
262 |
+
* @param string $destination
|
263 |
+
* @return bool
|
264 |
+
*
|
265 |
+
* @deprecated since version 2.0.0 (Supported only in php 5.5.11 and later)
|
266 |
+
*/
|
267 |
+
// private function copyBig($file, $destination)
|
268 |
+
// {
|
269 |
+
// $bytes = 0;
|
270 |
+
// $fileInput = new \SplFileObject($file, "rb");
|
271 |
+
// $fileOutput = new \SplFileObject($destination, 'w');
|
272 |
+
//
|
273 |
+
// $this->log("Copying big file; {$file} -> {$destination}");
|
274 |
+
//
|
275 |
+
// while (!$fileInput->eof())
|
276 |
+
// {
|
277 |
+
// $bytes += $fileOutput->fwrite($fileInput->fread($this->settings->batchSize));
|
278 |
+
// }
|
279 |
+
//
|
280 |
+
// $fileInput = null;
|
281 |
+
// $fileOutput= null;
|
282 |
+
//
|
283 |
+
// return ($bytes > 0);
|
284 |
+
// }
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Copy bigger files than $this->settings->batchSize
|
288 |
+
* @param string $src
|
289 |
+
* @param string $dst
|
290 |
+
* @param int $buffersize
|
291 |
+
* @return boolean
|
292 |
+
*/
|
293 |
+
private function copyBig($src, $dst, $buffersize) {
|
294 |
+
$src = fopen($src, 'r');
|
295 |
+
$dest = fopen($dst, 'w');
|
296 |
+
|
297 |
+
// Try first method:
|
298 |
+
while (!feof($src)) {
|
299 |
+
if (false === fwrite($dest, fread($src, $buffersize))) {
|
300 |
+
$error = true;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
// Try second method if first one failed
|
304 |
+
if (isset($error) && ($error === true)) {
|
305 |
+
while (!feof($src)) {
|
306 |
+
if (false === stream_copy_to_stream($src, $dest, 1024)) {
|
307 |
+
$this->log("Can not copy big file; {$src} -> {$dest}");
|
308 |
+
fclose($src);
|
309 |
+
fclose($dest);
|
310 |
+
return false;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
}
|
314 |
+
// Close any open handler
|
315 |
+
fclose($src);
|
316 |
+
fclose($dest);
|
317 |
+
return true;
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Check if file is excluded from copying process
|
322 |
+
*
|
323 |
+
* @param string $file filename including ending
|
324 |
+
* @return boolean
|
325 |
+
*/
|
326 |
+
private function isFileExcluded($file) {
|
327 |
+
$excluded = false;
|
328 |
+
foreach ($this->options->excludedFiles as $excludedFile) {
|
329 |
+
if (stripos(strrev($file), strrev($excludedFile)) === 0) {
|
330 |
+
$excluded = true;
|
331 |
+
break;
|
332 |
+
}
|
333 |
+
}
|
334 |
+
return $excluded;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Check if directory is excluded from copying
|
339 |
+
* @param string $directory
|
340 |
+
* @return bool
|
341 |
+
*/
|
342 |
+
private function isDirectoryExcluded($directory) {
|
343 |
+
foreach ($this->options->excludedDirectories as $excludedDirectory) {
|
344 |
+
if (strpos($directory, $excludedDirectory) === 0 && !$this->isExtraDirectory($directory)) {
|
345 |
+
return true;
|
346 |
+
}
|
347 |
+
}
|
348 |
+
|
349 |
+
return false;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Check if directory is an extra directory and should be copied
|
354 |
+
* @param string $directory
|
355 |
+
* @return boolean
|
356 |
+
*/
|
357 |
+
protected function isExtraDirectory($directory) {
|
358 |
+
foreach ($this->options->extraDirectories as $extraDirectory) {
|
359 |
+
if (strpos($directory, $extraDirectory) === 0) {
|
360 |
+
return true;
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
return false;
|
365 |
+
}
|
366 |
+
}
|
apps/Backend/Modules/Jobs/Finish.php
CHANGED
@@ -1,262 +1,121 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\WPStaging;
|
5 |
-
|
6 |
-
//error_reporting( E_ALL );
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Finish
|
10 |
-
* @package WPStaging\Backend\Modules\Jobs
|
11 |
-
*/
|
12 |
-
class Finish extends Job
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* Clone Key
|
16 |
-
* @var string
|
17 |
-
*/
|
18 |
-
private $clone = '';
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Start Module
|
22 |
-
* @return object
|
23 |
-
*/
|
24 |
-
public function start()
|
25 |
-
{
|
26 |
-
// sanitize the clone name before saving
|
27 |
-
$this->clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
28 |
-
|
29 |
-
// Delete Cache Files
|
30 |
-
$this->deleteCacheFiles();
|
31 |
-
|
32 |
-
// Prepare clone records & save scanned directories for delete job later
|
33 |
-
$this->prepareCloneDataRecords();
|
34 |
-
|
35 |
-
|
36 |
-
$return = array(
|
37 |
-
"directoryName" => $this->options->cloneDirectoryName,
|
38 |
-
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
39 |
-
"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
40 |
-
"number" => $this->options->cloneNumber,
|
41 |
-
"version" => \WPStaging\WPStaging::VERSION,
|
42 |
-
"status" => false,
|
43 |
-
"prefix" => $this->options->prefix,
|
44 |
-
"last_msg" => $this->logger->getLastLogMsg(),
|
45 |
-
"job" => $this->options->currentJob
|
46 |
-
);
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
$this->cache->delete("
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
*
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
"
|
92 |
-
"
|
93 |
-
"
|
94 |
-
"
|
95 |
-
"
|
96 |
-
"
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
//
|
116 |
-
//
|
117 |
-
//
|
118 |
-
// $
|
119 |
-
//
|
120 |
-
//
|
121 |
-
// $this->log("Cloning job has finished!");
|
122 |
-
// }
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Get Upload Directory
|
126 |
-
* @return string
|
127 |
-
*/
|
128 |
-
// private function getUploadDirectory()
|
129 |
-
// {
|
130 |
-
// $wpUploadDirectory = wp_get_upload_dir();
|
131 |
-
// $uploadDirectory = $wpUploadDirectory["basedir"] . DIRECTORY_SEPARATOR . WPStaging::SLUG;
|
132 |
-
//
|
133 |
-
// // Failed to create upload directory
|
134 |
-
// if (!is_dir($uploadDirectory) && !wp_mkdir_p($uploadDirectory))
|
135 |
-
// {
|
136 |
-
// $this->log("Upload directory ({$uploadDirectory}) doesn't exist and failed to create!");
|
137 |
-
// }
|
138 |
-
//
|
139 |
-
// $uploadDirectory = apply_filters("wpstg_get_upload_dir", $uploadDirectory);
|
140 |
-
//
|
141 |
-
// return rtrim($uploadDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
142 |
-
// }
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Get .htaccess rules
|
148 |
-
* @return string
|
149 |
-
*/
|
150 |
-
// private function getHtaccessRules()
|
151 |
-
// {
|
152 |
-
// // Prevent directory browsing and direct access to all files
|
153 |
-
// $rules = "<Files \"*\">\n";
|
154 |
-
// $rules .= "<IfModule mod_access.c>\n";
|
155 |
-
// $rules .= "Deny from all\n";
|
156 |
-
// $rules .= "</IfModule>\n";
|
157 |
-
// $rules .= "<IfModule !mod_access_compat>\n";
|
158 |
-
// $rules .= "<IfModule mod_authz_host.c>\n";
|
159 |
-
// $rules .= "Deny from all\n";
|
160 |
-
// $rules .= "</IfModule>\n";
|
161 |
-
// $rules .= "</IfModule>\n";
|
162 |
-
// $rules .= "<IfModule mod_access_compat>\n";
|
163 |
-
// $rules .= "Deny from all\n";
|
164 |
-
// $rules .= "</IfModule>\n";
|
165 |
-
// $rules .= "</Files>\n";
|
166 |
-
//
|
167 |
-
// return apply_filters("wpstg_protected_directory_htaccess_rules", $rules);
|
168 |
-
// }
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Update .htaccess file and its rules
|
172 |
-
* @param string $file
|
173 |
-
* @param string $contents
|
174 |
-
* @return bool
|
175 |
-
*/
|
176 |
-
// private function updateHTAccess($file, $contents)
|
177 |
-
// {
|
178 |
-
// return (
|
179 |
-
// (!$contents || $this->getHtaccessRules() !== $contents) &&
|
180 |
-
// false === @file_put_contents($file, $this->getHtaccessRules())
|
181 |
-
// );
|
182 |
-
// }
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Save HTAccess file
|
186 |
-
*/
|
187 |
-
// private function saveHTAccess()
|
188 |
-
// {
|
189 |
-
// $uploadDir = $this->getUploadDirectory();
|
190 |
-
// $htAccessFile = $uploadDir . ".htaccess";
|
191 |
-
//
|
192 |
-
// // .htaccess exists
|
193 |
-
// if (file_exists($htAccessFile))
|
194 |
-
// {
|
195 |
-
// $contents = @file_get_contents($htAccessFile);
|
196 |
-
//
|
197 |
-
// // Rules doesn't match, update .htaccess rules
|
198 |
-
// if (false === $this->updateHTAccess($htAccessFile, $contents))
|
199 |
-
// {
|
200 |
-
// $this->log("Failed to update {$htAccessFile}");
|
201 |
-
// }
|
202 |
-
// }
|
203 |
-
// // .htaccess doesn't exists and
|
204 |
-
// else if (wp_is_writable($uploadDir) && false === @file_put_contents($htAccessFile, $this->getHtaccessRules()))
|
205 |
-
// {
|
206 |
-
// $this->log("Failed to create {$htAccessFile}");
|
207 |
-
// }
|
208 |
-
// }
|
209 |
-
|
210 |
-
/**
|
211 |
-
* Save blank index file
|
212 |
-
* @return bool
|
213 |
-
*/
|
214 |
-
// private function saveBlankIndex()
|
215 |
-
// {
|
216 |
-
// $uploadDir = $this->getUploadDirectory();
|
217 |
-
// $indexFile = $uploadDir . "index.php";
|
218 |
-
//
|
219 |
-
// if (file_exists($indexFile))
|
220 |
-
// {
|
221 |
-
// return true;
|
222 |
-
// }
|
223 |
-
//
|
224 |
-
// $contents = "<?php" . PHP_EOL . "// WP-Staging protection file";
|
225 |
-
//
|
226 |
-
// if (!wp_is_writable($uploadDir) || false === @file_put_contents($indexFile, $contents))
|
227 |
-
// {
|
228 |
-
// $this->log("{$uploadDir} is not writable or couldn't generate {$indexFile}");
|
229 |
-
// return false;
|
230 |
-
// }
|
231 |
-
//
|
232 |
-
// return true;
|
233 |
-
// }
|
234 |
-
|
235 |
-
/**
|
236 |
-
* Prepare protect directories and files
|
237 |
-
* @param bool $force
|
238 |
-
*/
|
239 |
-
// protected function protectDirectoriesAndFiles($force = false)
|
240 |
-
// {
|
241 |
-
// // Don't execute
|
242 |
-
// if (true !== get_transient("wpstg_check_protection_files") && false === $force)
|
243 |
-
// {
|
244 |
-
// return;
|
245 |
-
// }
|
246 |
-
//
|
247 |
-
// // Save .htaccess file
|
248 |
-
// $this->saveHTAccess();
|
249 |
-
//
|
250 |
-
// // Save blank index.php file
|
251 |
-
// $this->saveBlankIndex();
|
252 |
-
//
|
253 |
-
// // TODO put blank index to upload directories?? Why??
|
254 |
-
//
|
255 |
-
// // Check files once a day
|
256 |
-
// set_transient("wpstg_check_protection_files", true, DAY_IN_SECONDS); // 24 hours in seconds
|
257 |
-
//
|
258 |
-
//
|
259 |
-
// }
|
260 |
-
|
261 |
-
|
262 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
use WPStaging\WPStaging;
|
5 |
+
|
6 |
+
//error_reporting( E_ALL );
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Finish
|
10 |
+
* @package WPStaging\Backend\Modules\Jobs
|
11 |
+
*/
|
12 |
+
class Finish extends Job
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Clone Key
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
private $clone = '';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Start Module
|
22 |
+
* @return object
|
23 |
+
*/
|
24 |
+
public function start()
|
25 |
+
{
|
26 |
+
// sanitize the clone name before saving
|
27 |
+
$this->clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
28 |
+
|
29 |
+
// Delete Cache Files
|
30 |
+
$this->deleteCacheFiles();
|
31 |
+
|
32 |
+
// Prepare clone records & save scanned directories for delete job later
|
33 |
+
$this->prepareCloneDataRecords();
|
34 |
+
|
35 |
+
|
36 |
+
$return = array(
|
37 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
38 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
39 |
+
"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
40 |
+
"number" => $this->options->cloneNumber,
|
41 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
42 |
+
"status" => false,
|
43 |
+
"prefix" => $this->options->prefix,
|
44 |
+
"last_msg" => $this->logger->getLastLogMsg(),
|
45 |
+
"job" => $this->options->currentJob
|
46 |
+
);
|
47 |
+
|
48 |
+
//$this->flush();
|
49 |
+
|
50 |
+
return (object) $return;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Delete Cache Files
|
55 |
+
*/
|
56 |
+
protected function deleteCacheFiles()
|
57 |
+
{
|
58 |
+
$this->log("Finish: Deleting clone job's cache files...");
|
59 |
+
|
60 |
+
// Clean cache files
|
61 |
+
$this->cache->delete("clone_options");
|
62 |
+
$this->cache->delete("files_to_copy");
|
63 |
+
|
64 |
+
$this->log("Finish: Clone job's cache files have been deleted!");
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Prepare clone records
|
69 |
+
* @return bool
|
70 |
+
*/
|
71 |
+
protected function prepareCloneDataRecords()
|
72 |
+
{
|
73 |
+
// Check if clones still exist
|
74 |
+
$this->log("Finish: Verifying existing clones...");
|
75 |
+
|
76 |
+
// Clone data already exists
|
77 |
+
if (isset($this->options->existingClones[$this->options->clone]))
|
78 |
+
{
|
79 |
+
$this->log("Finish: Clone data already exists, no need to update, the job finished");
|
80 |
+
return true;
|
81 |
+
}
|
82 |
+
|
83 |
+
// Save new clone data
|
84 |
+
$this->log("Finish: {$this->options->clone}'s clone job's data is not in database, generating data");
|
85 |
+
|
86 |
+
// sanitize the clone name before saving
|
87 |
+
//$clone = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
88 |
+
|
89 |
+
$this->options->existingClones[$this->clone] = array(
|
90 |
+
"directoryName" => $this->options->cloneDirectoryName,
|
91 |
+
"path" => ABSPATH . $this->options->cloneDirectoryName,
|
92 |
+
"url" => get_site_url() . '/' . $this->options->cloneDirectoryName,
|
93 |
+
"number" => $this->options->cloneNumber,
|
94 |
+
"version" => \WPStaging\WPStaging::VERSION,
|
95 |
+
"status" => false,
|
96 |
+
"prefix" => $this->options->prefix,
|
97 |
+
);
|
98 |
+
|
99 |
+
if (false === update_option("wpstg_existing_clones_beta", $this->options->existingClones))
|
100 |
+
{
|
101 |
+
$this->log("Finish: Failed to save {$this->options->clone}'s clone job data to database'");
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
+
return true;
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Flush wpdb cache and permalinks
|
111 |
+
* @global type $wp_rewrite
|
112 |
+
*/
|
113 |
+
// protected function flush() {
|
114 |
+
// // flush rewrite rules to prevent 404s
|
115 |
+
// // and other oddities
|
116 |
+
// wp_cache_flush();
|
117 |
+
// global $wp_rewrite;
|
118 |
+
// $wp_rewrite->init();
|
119 |
+
// flush_rewrite_rules(true); // true = hard refresh, recreates the .htaccess file
|
120 |
+
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
apps/Backend/Modules/Jobs/Job.php
CHANGED
@@ -1,485 +1,488 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\Backend\Modules\Jobs\Interfaces\JobInterface;
|
11 |
-
use WPStaging\Utils\Logger;
|
12 |
-
use WPStaging\WPStaging;
|
13 |
-
use WPStaging\Utils\Cache;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Class Job
|
17 |
-
* @package WPStaging\Backend\Modules\Jobs
|
18 |
-
*/
|
19 |
-
abstract class Job implements JobInterface
|
20 |
-
{
|
21 |
-
|
22 |
-
const EXECUTION_TIME_RATIO = 0.8;
|
23 |
-
|
24 |
-
const MAX_MEMORY_RATIO = 0.8;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @var Cache
|
28 |
-
*/
|
29 |
-
protected $cache;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* @var Logger
|
33 |
-
*/
|
34 |
-
protected $logger;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @var bool
|
38 |
-
*/
|
39 |
-
protected $hasLoggedFileNameSet = false;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @var object
|
43 |
-
*/
|
44 |
-
protected $options;
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @var object
|
48 |
-
*/
|
49 |
-
protected $settings;
|
50 |
-
|
51 |
-
/**
|
52 |
-
* System total maximum memory consumption
|
53 |
-
* @var int
|
54 |
-
*/
|
55 |
-
protected $maxMemoryLimit;
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Script maximum memory consumption
|
59 |
-
* @var int
|
60 |
-
*/
|
61 |
-
protected $memoryLimit;
|
62 |
-
|
63 |
-
/**
|
64 |
-
* @var int
|
65 |
-
*/
|
66 |
-
protected $maxExecutionTime;
|
67 |
-
|
68 |
-
|
69 |
-
/**
|
70 |
-
* @var int
|
71 |
-
*/
|
72 |
-
protected $executionLimit;
|
73 |
-
|
74 |
-
/**
|
75 |
-
* @var int
|
76 |
-
*/
|
77 |
-
protected $totalRecursion;
|
78 |
-
|
79 |
-
/**
|
80 |
-
* @var int
|
81 |
-
*/
|
82 |
-
protected $maxRecursionLimit;
|
83 |
-
|
84 |
-
/**
|
85 |
-
* @var int
|
86 |
-
*/
|
87 |
-
protected $start;
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Job constructor.
|
91 |
-
*/
|
92 |
-
public function __construct()
|
93 |
-
{
|
94 |
-
// Get max limits
|
95 |
-
$this->start = $this->time();
|
96 |
-
$this->maxMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
//
|
103 |
-
//
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
$this->
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
!isset($this->settings->
|
129 |
-
!isset($this->settings->
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
$this->
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
*
|
146 |
-
*
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
$this->settings->
|
179 |
-
$this->settings->
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
$
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
$this->
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
*
|
221 |
-
* @
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
* @
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
//
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
case '
|
266 |
-
$bytes *=
|
267 |
-
break;
|
268 |
-
case '
|
269 |
-
$bytes *= (1024 * 1024
|
270 |
-
break;
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
$
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
//
|
372 |
-
$this->
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
*
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
//
|
388 |
-
//
|
389 |
-
//
|
390 |
-
//
|
391 |
-
//
|
392 |
-
//
|
393 |
-
//
|
394 |
-
//
|
395 |
-
//
|
396 |
-
//
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
*
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
//
|
408 |
-
//
|
409 |
-
//
|
410 |
-
//
|
411 |
-
//
|
412 |
-
//
|
413 |
-
//
|
414 |
-
//
|
415 |
-
//
|
416 |
-
//
|
417 |
-
//
|
418 |
-
//
|
419 |
-
//
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
'
|
483 |
-
|
484 |
-
|
|
|
|
|
|
|
485 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\Backend\Modules\Jobs\Interfaces\JobInterface;
|
11 |
+
use WPStaging\Utils\Logger;
|
12 |
+
use WPStaging\WPStaging;
|
13 |
+
use WPStaging\Utils\Cache;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Class Job
|
17 |
+
* @package WPStaging\Backend\Modules\Jobs
|
18 |
+
*/
|
19 |
+
abstract class Job implements JobInterface
|
20 |
+
{
|
21 |
+
|
22 |
+
const EXECUTION_TIME_RATIO = 0.8;
|
23 |
+
|
24 |
+
const MAX_MEMORY_RATIO = 0.8;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var Cache
|
28 |
+
*/
|
29 |
+
protected $cache;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var Logger
|
33 |
+
*/
|
34 |
+
protected $logger;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var bool
|
38 |
+
*/
|
39 |
+
protected $hasLoggedFileNameSet = false;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var object
|
43 |
+
*/
|
44 |
+
protected $options;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var object
|
48 |
+
*/
|
49 |
+
protected $settings;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* System total maximum memory consumption
|
53 |
+
* @var int
|
54 |
+
*/
|
55 |
+
protected $maxMemoryLimit;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Script maximum memory consumption
|
59 |
+
* @var int
|
60 |
+
*/
|
61 |
+
protected $memoryLimit;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @var int
|
65 |
+
*/
|
66 |
+
protected $maxExecutionTime;
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var int
|
71 |
+
*/
|
72 |
+
protected $executionLimit;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var int
|
76 |
+
*/
|
77 |
+
protected $totalRecursion;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @var int
|
81 |
+
*/
|
82 |
+
protected $maxRecursionLimit;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @var int
|
86 |
+
*/
|
87 |
+
protected $start;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Job constructor.
|
91 |
+
*/
|
92 |
+
public function __construct()
|
93 |
+
{
|
94 |
+
// Get max limits
|
95 |
+
$this->start = $this->time();
|
96 |
+
$this->maxMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
97 |
+
|
98 |
+
|
99 |
+
//$this->maxExecutionTime = (int) ini_get("max_execution_time");
|
100 |
+
$this->maxExecutionTime = (int) 30;
|
101 |
+
|
102 |
+
// if ($this->maxExecutionTime < 1 || $this->maxExecutionTime > 30)
|
103 |
+
// {
|
104 |
+
// $this->maxExecutionTime = 30;
|
105 |
+
// }
|
106 |
+
|
107 |
+
// Services
|
108 |
+
$this->cache = new Cache(-1, \WPStaging\WPStaging::getContentDir());
|
109 |
+
$this->logger = WPStaging::getInstance()->get("logger");
|
110 |
+
|
111 |
+
// Settings and Options
|
112 |
+
$this->options = $this->cache->get("clone_options");
|
113 |
+
//$this->settings = json_decode(json_encode(get_option("wpstg_settings", array())));
|
114 |
+
$this->settings = (object) get_option("wpstg_settings", array());
|
115 |
+
|
116 |
+
if (!$this->options)
|
117 |
+
{
|
118 |
+
$this->options = new \stdClass();
|
119 |
+
}
|
120 |
+
|
121 |
+
if (isset($this->options->existingClones) && is_object($this->options->existingClones))
|
122 |
+
{
|
123 |
+
$this->options->existingClones = json_decode(json_encode($this->options->existingClones), true);
|
124 |
+
}
|
125 |
+
|
126 |
+
// check default options
|
127 |
+
if ( !isset($this->settings) ||
|
128 |
+
!isset($this->settings->queryLimit) ||
|
129 |
+
!isset($this->settings->batchSize) ||
|
130 |
+
!isset($this->settings->cpuLoad) ||
|
131 |
+
!isset($this->settings->fileLimit)
|
132 |
+
)
|
133 |
+
|
134 |
+
{
|
135 |
+
$this->settings = new \stdClass();
|
136 |
+
$this->setDefaultSettings();
|
137 |
+
}
|
138 |
+
|
139 |
+
// Set limits accordingly to CPU LIMITS
|
140 |
+
$this->setLimits();
|
141 |
+
|
142 |
+
$this->maxRecursionLimit = (int) ini_get("xdebug.max_nesting_level");
|
143 |
+
|
144 |
+
/*
|
145 |
+
* This is needed to make sure that maxRecursionLimit = -1
|
146 |
+
* if xdebug is not used in production env.
|
147 |
+
* For using xdebug, maxRecursionLimit must be larger
|
148 |
+
* otherwise xdebug is throwing an error 500 while debugging
|
149 |
+
*/
|
150 |
+
if ($this->maxRecursionLimit < 1)
|
151 |
+
{
|
152 |
+
$this->maxRecursionLimit = -1;
|
153 |
+
}
|
154 |
+
else
|
155 |
+
{
|
156 |
+
$this->maxRecursionLimit = $this->maxRecursionLimit - 50; // just to make sure
|
157 |
+
}
|
158 |
+
|
159 |
+
if (method_exists($this, "initialize"))
|
160 |
+
{
|
161 |
+
$this->initialize();
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Job destructor
|
167 |
+
*/
|
168 |
+
public function __destruct()
|
169 |
+
{
|
170 |
+
// Commit logs
|
171 |
+
$this->logger->commit();
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Set default settings
|
176 |
+
*/
|
177 |
+
protected function setDefaultSettings(){
|
178 |
+
$this->settings->queryLimit = "5000";
|
179 |
+
$this->settings->fileLimit = "1";
|
180 |
+
$this->settings->batchSize = "2";
|
181 |
+
$this->settings->cpuLoad = 'medium';
|
182 |
+
update_option('wpstg_settings', $this->settings);
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Set limits accordingly to
|
187 |
+
*/
|
188 |
+
protected function setLimits()
|
189 |
+
{
|
190 |
+
|
191 |
+
if (!isset($this->settings->cpuLoad))
|
192 |
+
{
|
193 |
+
$this->settings->cpuLoad = "medium";
|
194 |
+
}
|
195 |
+
|
196 |
+
$memoryLimit= self::MAX_MEMORY_RATIO;
|
197 |
+
$timeLimit = self::EXECUTION_TIME_RATIO;
|
198 |
+
|
199 |
+
switch($this->settings->cpuLoad)
|
200 |
+
{
|
201 |
+
case "medium":
|
202 |
+
//$memoryLimit= $memoryLimit / 2; // 0.4
|
203 |
+
$timeLimit = $timeLimit / 2;
|
204 |
+
break;
|
205 |
+
case "low":
|
206 |
+
//$memoryLimit= $memoryLimit / 4; // 0.2
|
207 |
+
$timeLimit = $timeLimit / 4;
|
208 |
+
break;
|
209 |
+
|
210 |
+
case "fast": // 0.8
|
211 |
+
default:
|
212 |
+
break;
|
213 |
+
}
|
214 |
+
|
215 |
+
$this->memoryLimit = $this->maxMemoryLimit * $memoryLimit;
|
216 |
+
$this->executionLimit = $this->maxExecutionTime * $timeLimit;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Save options
|
221 |
+
* @param null|array|object $options
|
222 |
+
* @return bool
|
223 |
+
*/
|
224 |
+
protected function saveOptions($options = null)
|
225 |
+
{
|
226 |
+
// Get default options
|
227 |
+
if (null === $options)
|
228 |
+
{
|
229 |
+
$options = $this->options;
|
230 |
+
}
|
231 |
+
|
232 |
+
// Ensure that it is an object
|
233 |
+
$options = json_decode(json_encode($options));
|
234 |
+
return $this->cache->save("clone_options", $options);
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* @return object
|
239 |
+
*/
|
240 |
+
public function getOptions()
|
241 |
+
{
|
242 |
+
return $this->options;
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* @param string $memory
|
247 |
+
* @return int
|
248 |
+
*/
|
249 |
+
protected function getMemoryInBytes($memory)
|
250 |
+
{
|
251 |
+
// Handle unlimited ones
|
252 |
+
if (1 > (int) $memory)
|
253 |
+
{
|
254 |
+
//return (int) $memory;
|
255 |
+
// 128 MB default value
|
256 |
+
return (int) 134217728;
|
257 |
+
}
|
258 |
+
|
259 |
+
$bytes = (int) $memory; // grab only the number
|
260 |
+
$size = trim(str_replace($bytes, null, strtolower($memory))); // strip away number and lower-case it
|
261 |
+
|
262 |
+
// Actual calculation
|
263 |
+
switch($size)
|
264 |
+
{
|
265 |
+
case 'k':
|
266 |
+
$bytes *= 1024;
|
267 |
+
break;
|
268 |
+
case 'm':
|
269 |
+
$bytes *= (1024 * 1024);
|
270 |
+
break;
|
271 |
+
case 'g':
|
272 |
+
$bytes *= (1024 * 1024 * 1024);
|
273 |
+
break;
|
274 |
+
}
|
275 |
+
|
276 |
+
return $bytes;
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Format bytes into ini_set favorable form
|
281 |
+
* @param int $bytes
|
282 |
+
* @return string
|
283 |
+
*/
|
284 |
+
protected function formatBytes($bytes)
|
285 |
+
{
|
286 |
+
if ((int) $bytes < 1)
|
287 |
+
{
|
288 |
+
return '';
|
289 |
+
}
|
290 |
+
|
291 |
+
$units = array('B', 'K', 'M', 'G'); // G since PHP 5.1.x so we are good!
|
292 |
+
|
293 |
+
$bytes = (int) $bytes;
|
294 |
+
$base = log($bytes) / log(1000);
|
295 |
+
$pow = pow(1000, $base - floor($base));
|
296 |
+
|
297 |
+
return round($pow, 0) . $units[(int) floor($base)];
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Get current time in seconds
|
302 |
+
* @return float
|
303 |
+
*/
|
304 |
+
protected function time()
|
305 |
+
{
|
306 |
+
$time = microtime();
|
307 |
+
$time = explode(' ', $time);
|
308 |
+
$time = $time[1] + $time[0];
|
309 |
+
return $time;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @return bool
|
314 |
+
*/
|
315 |
+
protected function isOverThreshold()
|
316 |
+
{
|
317 |
+
// Check if the memory is over threshold
|
318 |
+
$usedMemory = (int) @memory_get_usage(true);
|
319 |
+
|
320 |
+
$this->debugLog('Used Memory: ' . $this->formatBytes( $usedMemory ) . ' Max Memory Limit: ' . $this->formatBytes( $this->maxMemoryLimit ) . ' Max Script Memory Limit: ' . $this->formatBytes( $this->memoryLimit), Logger::TYPE_DEBUG );
|
321 |
+
|
322 |
+
if ($usedMemory >= $this->memoryLimit)
|
323 |
+
{
|
324 |
+
$this->log('Used Memory: ' . $this->formatBytes($usedMemory) . ' Memory Limit: ' . $this->formatBytes($this->maxMemoryLimit) . ' Max Script memory limit: ' . $this->formatBytes( $this->memoryLimit ), Logger::TYPE_ERROR );
|
325 |
+
//$this->resetMemory();
|
326 |
+
return true;
|
327 |
+
}
|
328 |
+
|
329 |
+
if ($this->isRecursionLimit())
|
330 |
+
{
|
331 |
+
//$this->log('RESET RECURSION');
|
332 |
+
return true;
|
333 |
+
}
|
334 |
+
|
335 |
+
// Check if execution time is over threshold
|
336 |
+
///$time = round($this->start + $this->time(), 4);
|
337 |
+
$time = round($this->time() - $this->start, 4);
|
338 |
+
|
339 |
+
if ($time >= $this->executionLimit)
|
340 |
+
{
|
341 |
+
$this->debugLog('RESET TIME: current time: ' . $time . ', Start Time: ' . $this->start . ', exec time limit: ' . $this->executionLimit);
|
342 |
+
return true;
|
343 |
+
}
|
344 |
+
|
345 |
+
return false;
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Attempt to reset memory
|
350 |
+
* @return bool
|
351 |
+
* memory
|
352 |
+
*/
|
353 |
+
// protected function resetMemory()
|
354 |
+
// {
|
355 |
+
// $newMemoryLimit = $this->maxMemoryLimit * 2;
|
356 |
+
//
|
357 |
+
// // Failed to set
|
358 |
+
// if (false === ini_set("memory_limit", $this->formatBytes($newMemoryLimit)))
|
359 |
+
// {
|
360 |
+
// $this->log('Can not free some memory', Logger::TYPE_CRITICAL);
|
361 |
+
// return false;
|
362 |
+
// }
|
363 |
+
//
|
364 |
+
// // Double checking
|
365 |
+
// $newMemoryLimit = $this->getMemoryInBytes(@ini_get("memory_limit"));
|
366 |
+
// if ($newMemoryLimit <= $this->maxMemoryLimit)
|
367 |
+
// {
|
368 |
+
// return false;
|
369 |
+
// }
|
370 |
+
//
|
371 |
+
// // Set the new Maximum memory limit
|
372 |
+
// $this->maxMemoryLimit = $newMemoryLimit;
|
373 |
+
//
|
374 |
+
// // Calculate threshold limit
|
375 |
+
// $this->memoryLimit = $newMemoryLimit * self::MAX_MEMORY_RATIO;
|
376 |
+
//
|
377 |
+
// return true;
|
378 |
+
// }
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Attempt to reset time
|
382 |
+
* @return bool
|
383 |
+
*
|
384 |
+
* @deprecated since version 2.0.0
|
385 |
+
|
386 |
+
*/
|
387 |
+
// protected function resetTime()
|
388 |
+
// {
|
389 |
+
// // Attempt to reset timeout
|
390 |
+
// if (!@set_time_limit($this->maxExecutionTime))
|
391 |
+
// {
|
392 |
+
// return false;
|
393 |
+
// }
|
394 |
+
//
|
395 |
+
// // Increase execution limit
|
396 |
+
// $this->executionLimit = $this->executionLimit * 2;
|
397 |
+
//
|
398 |
+
// return true;
|
399 |
+
// }
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Reset time limit and memory
|
403 |
+
* @return bool
|
404 |
+
*
|
405 |
+
* @deprecated since version 2.0.0
|
406 |
+
*/
|
407 |
+
// protected function reset()
|
408 |
+
// {
|
409 |
+
// // Attempt to reset time
|
410 |
+
// if (!$this->resetTime())
|
411 |
+
// {
|
412 |
+
// return false;
|
413 |
+
// }
|
414 |
+
//
|
415 |
+
// // Attempt to reset memory
|
416 |
+
// if (!$this->resetMemory())
|
417 |
+
// {
|
418 |
+
// return false;
|
419 |
+
// }
|
420 |
+
//
|
421 |
+
// return true;
|
422 |
+
// }
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Checks if calls are over recursion limit
|
426 |
+
* @return bool
|
427 |
+
*/
|
428 |
+
protected function isRecursionLimit()
|
429 |
+
{
|
430 |
+
return ($this->maxRecursionLimit > 0 && $this->totalRecursion >= $this->maxRecursionLimit);
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* @param string $msg
|
435 |
+
* @param string $type
|
436 |
+
*/
|
437 |
+
protected function log($msg, $type = Logger::TYPE_INFO)
|
438 |
+
{
|
439 |
+
|
440 |
+
if (!isset($this->options->clone)){
|
441 |
+
$this->options->clone = date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
|
442 |
+
}
|
443 |
+
|
444 |
+
if (false === $this->hasLoggedFileNameSet && 0 < strlen($this->options->clone))
|
445 |
+
{
|
446 |
+
$this->logger->setFileName($this->options->clone);
|
447 |
+
$this->hasLoggedFileNameSet = true;
|
448 |
+
}
|
449 |
+
|
450 |
+
$this->logger->add($msg, $type);
|
451 |
+
}
|
452 |
+
/**
|
453 |
+
* @param string $msg
|
454 |
+
* @param string $type
|
455 |
+
*/
|
456 |
+
protected function debugLog($msg, $type = Logger::TYPE_INFO)
|
457 |
+
{
|
458 |
+
|
459 |
+
if (!isset($this->options->clone)){
|
460 |
+
$this->options->clone = date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
|
461 |
+
}
|
462 |
+
|
463 |
+
if (false === $this->hasLoggedFileNameSet && 0 < strlen($this->options->clone))
|
464 |
+
{
|
465 |
+
$this->logger->setFileName($this->options->clone);
|
466 |
+
$this->hasLoggedFileNameSet = true;
|
467 |
+
}
|
468 |
+
|
469 |
+
|
470 |
+
if (isset($this->settings->debugMode)){
|
471 |
+
$this->logger->add($msg, $type);
|
472 |
+
}
|
473 |
+
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* Throw a errror message via json and stop further execution
|
478 |
+
* @param string $message
|
479 |
+
*/
|
480 |
+
protected function returnException($message = ''){
|
481 |
+
wp_die( json_encode(array(
|
482 |
+
'job' => isset($this->options->currentJob) ? $this->options->currentJob : '',
|
483 |
+
'status' => false,
|
484 |
+
'message' => $message,
|
485 |
+
'error' => true
|
486 |
+
)));
|
487 |
+
}
|
488 |
}
|
apps/Backend/Modules/Jobs/JobExecutable.php
CHANGED
@@ -1,112 +1,112 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Class JobExecutable
|
13 |
-
* I'm sorry for such mess, we need to support PHP 5.3
|
14 |
-
* @package WPStaging\Backend\Modules\Jobs
|
15 |
-
*/
|
16 |
-
abstract class JobExecutable extends Job
|
17 |
-
{
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @var array
|
21 |
-
*/
|
22 |
-
protected $response = array(
|
23 |
-
"status" => false,
|
24 |
-
"percentage" => 0,
|
25 |
-
"total" => 0,
|
26 |
-
"step" => 0,
|
27 |
-
"last_msg" => '',
|
28 |
-
);
|
29 |
-
|
30 |
-
/**
|
31 |
-
* JobExecutable constructor.
|
32 |
-
*/
|
33 |
-
public function __construct()
|
34 |
-
{
|
35 |
-
parent::__construct();
|
36 |
-
|
37 |
-
// Calculate total steps
|
38 |
-
$this->calculateTotalSteps();
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Prepare Response Array
|
43 |
-
* @param bool $status
|
44 |
-
* @param bool $incrementCurrentStep
|
45 |
-
* @return array
|
46 |
-
*/
|
47 |
-
protected function prepareResponse($status = false, $incrementCurrentStep = true)
|
48 |
-
{
|
49 |
-
if ($incrementCurrentStep)
|
50 |
-
{
|
51 |
-
$this->options->currentStep++;
|
52 |
-
}
|
53 |
-
|
54 |
-
$percentage = round(($this->options->currentStep / $this->options->totalSteps) * 100);
|
55 |
-
$percentage = (100 < $percentage) ? 100 : $percentage;
|
56 |
-
|
57 |
-
return $this->response = array(
|
58 |
-
"status" => $status,
|
59 |
-
"percentage" => $percentage,
|
60 |
-
"total" => $this->options->totalSteps,
|
61 |
-
"step" => $this->options->currentStep,
|
62 |
-
"job" => $this->options->currentJob,
|
63 |
-
"last_msg" => $this->logger->getLastLogMsg(),
|
64 |
-
"running_time" => $this->time() - time(),
|
65 |
-
"job_done" => $status
|
66 |
-
);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Start Module
|
71 |
-
* @return object
|
72 |
-
*/
|
73 |
-
public function start()
|
74 |
-
{
|
75 |
-
// Execute steps
|
76 |
-
$this->run();
|
77 |
-
|
78 |
-
// Save option, progress
|
79 |
-
$this->saveOptions();
|
80 |
-
|
81 |
-
return (object) $this->response;
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Run Steps
|
86 |
-
*/
|
87 |
-
protected function run()
|
88 |
-
{
|
89 |
-
// Execute steps
|
90 |
-
for ($i = 0; $i < $this->options->totalSteps; $i++)
|
91 |
-
{
|
92 |
-
// Job is finished or over threshold limits was hit
|
93 |
-
if (!$this->execute())
|
94 |
-
{
|
95 |
-
break;
|
96 |
-
}
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
102 |
-
* @return void
|
103 |
-
*/
|
104 |
-
abstract protected function calculateTotalSteps();
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Execute the Current Step
|
108 |
-
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
109 |
-
* @return bool
|
110 |
-
*/
|
111 |
-
abstract protected function execute();
|
112 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Class JobExecutable
|
13 |
+
* I'm sorry for such mess, we need to support PHP 5.3
|
14 |
+
* @package WPStaging\Backend\Modules\Jobs
|
15 |
+
*/
|
16 |
+
abstract class JobExecutable extends Job
|
17 |
+
{
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var array
|
21 |
+
*/
|
22 |
+
protected $response = array(
|
23 |
+
"status" => false,
|
24 |
+
"percentage" => 0,
|
25 |
+
"total" => 0,
|
26 |
+
"step" => 0,
|
27 |
+
"last_msg" => '',
|
28 |
+
);
|
29 |
+
|
30 |
+
/**
|
31 |
+
* JobExecutable constructor.
|
32 |
+
*/
|
33 |
+
public function __construct()
|
34 |
+
{
|
35 |
+
parent::__construct();
|
36 |
+
|
37 |
+
// Calculate total steps
|
38 |
+
$this->calculateTotalSteps();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Prepare Response Array
|
43 |
+
* @param bool $status
|
44 |
+
* @param bool $incrementCurrentStep
|
45 |
+
* @return array
|
46 |
+
*/
|
47 |
+
protected function prepareResponse($status = false, $incrementCurrentStep = true)
|
48 |
+
{
|
49 |
+
if ($incrementCurrentStep)
|
50 |
+
{
|
51 |
+
$this->options->currentStep++;
|
52 |
+
}
|
53 |
+
|
54 |
+
$percentage = round(($this->options->currentStep / $this->options->totalSteps) * 100);
|
55 |
+
$percentage = (100 < $percentage) ? 100 : $percentage;
|
56 |
+
|
57 |
+
return $this->response = array(
|
58 |
+
"status" => $status,
|
59 |
+
"percentage" => $percentage,
|
60 |
+
"total" => $this->options->totalSteps,
|
61 |
+
"step" => $this->options->currentStep,
|
62 |
+
"job" => $this->options->currentJob,
|
63 |
+
"last_msg" => $this->logger->getLastLogMsg(),
|
64 |
+
"running_time" => $this->time() - time(),
|
65 |
+
"job_done" => $status
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Start Module
|
71 |
+
* @return object
|
72 |
+
*/
|
73 |
+
public function start()
|
74 |
+
{
|
75 |
+
// Execute steps
|
76 |
+
$this->run();
|
77 |
+
|
78 |
+
// Save option, progress
|
79 |
+
$this->saveOptions();
|
80 |
+
|
81 |
+
return (object) $this->response;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Run Steps
|
86 |
+
*/
|
87 |
+
protected function run()
|
88 |
+
{
|
89 |
+
// Execute steps
|
90 |
+
for ($i = 0; $i < $this->options->totalSteps; $i++)
|
91 |
+
{
|
92 |
+
// Job is finished or over threshold limits was hit
|
93 |
+
if (!$this->execute())
|
94 |
+
{
|
95 |
+
break;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Calculate Total Steps in This Job and Assign It to $this->options->totalSteps
|
102 |
+
* @return void
|
103 |
+
*/
|
104 |
+
abstract protected function calculateTotalSteps();
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Execute the Current Step
|
108 |
+
* Returns false when over threshold limits are hit or when the job is done, true otherwise
|
109 |
+
* @return bool
|
110 |
+
*/
|
111 |
+
abstract protected function execute();
|
112 |
}
|
apps/Backend/Modules/Jobs/Scan.php
CHANGED
@@ -1,402 +1,407 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\Utils\Directories;
|
11 |
-
use WPStaging\WPStaging;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Class Scan
|
15 |
-
* @package WPStaging\Backend\Modules\Jobs
|
16 |
-
*/
|
17 |
-
class Scan extends Job
|
18 |
-
{
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @var array
|
22 |
-
*/
|
23 |
-
private $directories = array();
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @var Directories
|
27 |
-
*/
|
28 |
-
private $objDirectories;
|
29 |
-
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Upon class initialization
|
33 |
-
*/
|
34 |
-
protected function initialize()
|
35 |
-
{
|
36 |
-
$this->objDirectories = new Directories();
|
37 |
-
|
38 |
-
// Database Tables
|
39 |
-
$this->getTables();
|
40 |
-
|
41 |
-
// Get directories
|
42 |
-
$this->directories();
|
43 |
-
|
44 |
-
$this->db = WPStaging::getInstance()->get('wpdb');
|
45 |
-
$this->prefix = $this->db->prefix;
|
46 |
-
|
47 |
-
|
48 |
-
}
|
49 |
-
|
50 |
-
/**
|
51 |
-
* Start Module
|
52 |
-
* @return $this
|
53 |
-
*/
|
54 |
-
public function start()
|
55 |
-
{
|
56 |
-
// Basic Options
|
57 |
-
$this->options->root = str_replace(array("\\", '/'), DIRECTORY_SEPARATOR, ABSPATH);
|
58 |
-
$this->options->existingClones = get_option("wpstg_existing_clones_beta", array());
|
59 |
-
$this->options->current = null;
|
60 |
-
|
61 |
-
if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $this->options->existingClones))
|
62 |
-
{
|
63 |
-
$this->options->current = $_POST["clone"];
|
64 |
-
}
|
65 |
-
|
66 |
-
// Tables
|
67 |
-
//$this->options->excludedTables = array();
|
68 |
-
$this->options->clonedTables = array();
|
69 |
-
|
70 |
-
// Files
|
71 |
-
$this->options->totalFiles = 0;
|
72 |
-
$this->options->totalFileSize = 0;
|
73 |
-
$this->options->copiedFiles = 0;
|
74 |
-
|
75 |
-
|
76 |
-
// Directories
|
77 |
-
$this->options->includedDirectories = array();
|
78 |
-
$this->options->excludedDirectories = array();
|
79 |
-
$this->options->extraDirectories = array();
|
80 |
-
$this->options->directoriesToCopy = array();
|
81 |
-
$this->options->scannedDirectories = array();
|
82 |
-
|
83 |
-
// Job
|
84 |
-
$this->options->currentJob = "database";
|
85 |
-
$this->options->currentStep = 0;
|
86 |
-
$this->options->totalSteps = 0;
|
87 |
-
|
88 |
-
// Delete previous cached files
|
89 |
-
$this->cache->delete("files_to_copy");
|
90 |
-
$this->cache->delete("clone_options");
|
91 |
-
//$this->cache->delete("files_to_verify");
|
92 |
-
//$this->cache->delete("files_verified");
|
93 |
-
|
94 |
-
// Save options
|
95 |
-
$this->saveOptions();
|
96 |
-
|
97 |
-
return $this;
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Format bytes into human readable form
|
102 |
-
* @param int $bytes
|
103 |
-
* @param int $precision
|
104 |
-
* @return string
|
105 |
-
*/
|
106 |
-
public function formatSize($bytes, $precision = 2)
|
107 |
-
{
|
108 |
-
if ((double) $bytes < 1)
|
109 |
-
{
|
110 |
-
return '';
|
111 |
-
}
|
112 |
-
|
113 |
-
$units = array('B', "KB", "MB", "GB", "TB");
|
114 |
-
|
115 |
-
$bytes = (double) $bytes;
|
116 |
-
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
117 |
-
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
118 |
-
|
119 |
-
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* @param null|string $directories
|
124 |
-
* @param bool $forceDisabled
|
125 |
-
* @return string
|
126 |
-
*/
|
127 |
-
public function directoryListing($directories = null, $forceDisabled = false)
|
128 |
-
{
|
129 |
-
if (null == $directories)
|
130 |
-
{
|
131 |
-
$directories = $this->directories;
|
132 |
-
}
|
133 |
-
|
134 |
-
$output = '';
|
135 |
-
foreach ($directories as $name => $directory)
|
136 |
-
{
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
);
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
$output .= "
|
155 |
-
|
156 |
-
|
157 |
-
if (
|
158 |
-
$output .= "
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
if (
|
164 |
-
{
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
if(
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
{
|
222 |
-
$
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
$
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
//
|
240 |
-
if (0
|
241 |
-
{
|
242 |
-
|
243 |
-
}
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
$this->
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
$this->
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
$currentArray
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
$
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
);
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
|
|
|
|
|
|
|
|
|
|
402 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\Utils\Directories;
|
11 |
+
use WPStaging\WPStaging;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class Scan
|
15 |
+
* @package WPStaging\Backend\Modules\Jobs
|
16 |
+
*/
|
17 |
+
class Scan extends Job
|
18 |
+
{
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var array
|
22 |
+
*/
|
23 |
+
private $directories = array();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var Directories
|
27 |
+
*/
|
28 |
+
private $objDirectories;
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Upon class initialization
|
33 |
+
*/
|
34 |
+
protected function initialize()
|
35 |
+
{
|
36 |
+
$this->objDirectories = new Directories();
|
37 |
+
|
38 |
+
// Database Tables
|
39 |
+
$this->getTables();
|
40 |
+
|
41 |
+
// Get directories
|
42 |
+
$this->directories();
|
43 |
+
|
44 |
+
$this->db = WPStaging::getInstance()->get('wpdb');
|
45 |
+
$this->prefix = $this->db->prefix;
|
46 |
+
|
47 |
+
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Start Module
|
52 |
+
* @return $this
|
53 |
+
*/
|
54 |
+
public function start()
|
55 |
+
{
|
56 |
+
// Basic Options
|
57 |
+
$this->options->root = str_replace(array("\\", '/'), DIRECTORY_SEPARATOR, ABSPATH);
|
58 |
+
$this->options->existingClones = get_option("wpstg_existing_clones_beta", array());
|
59 |
+
$this->options->current = null;
|
60 |
+
|
61 |
+
if (isset($_POST["clone"]) && array_key_exists($_POST["clone"], $this->options->existingClones))
|
62 |
+
{
|
63 |
+
$this->options->current = $_POST["clone"];
|
64 |
+
}
|
65 |
+
|
66 |
+
// Tables
|
67 |
+
//$this->options->excludedTables = array();
|
68 |
+
$this->options->clonedTables = array();
|
69 |
+
|
70 |
+
// Files
|
71 |
+
$this->options->totalFiles = 0;
|
72 |
+
$this->options->totalFileSize = 0;
|
73 |
+
$this->options->copiedFiles = 0;
|
74 |
+
|
75 |
+
|
76 |
+
// Directories
|
77 |
+
$this->options->includedDirectories = array();
|
78 |
+
$this->options->excludedDirectories = array();
|
79 |
+
$this->options->extraDirectories = array();
|
80 |
+
$this->options->directoriesToCopy = array();
|
81 |
+
$this->options->scannedDirectories = array();
|
82 |
+
|
83 |
+
// Job
|
84 |
+
$this->options->currentJob = "database";
|
85 |
+
$this->options->currentStep = 0;
|
86 |
+
$this->options->totalSteps = 0;
|
87 |
+
|
88 |
+
// Delete previous cached files
|
89 |
+
$this->cache->delete("files_to_copy");
|
90 |
+
$this->cache->delete("clone_options");
|
91 |
+
//$this->cache->delete("files_to_verify");
|
92 |
+
//$this->cache->delete("files_verified");
|
93 |
+
|
94 |
+
// Save options
|
95 |
+
$this->saveOptions();
|
96 |
+
|
97 |
+
return $this;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Format bytes into human readable form
|
102 |
+
* @param int $bytes
|
103 |
+
* @param int $precision
|
104 |
+
* @return string
|
105 |
+
*/
|
106 |
+
public function formatSize($bytes, $precision = 2)
|
107 |
+
{
|
108 |
+
if ((double) $bytes < 1)
|
109 |
+
{
|
110 |
+
return '';
|
111 |
+
}
|
112 |
+
|
113 |
+
$units = array('B', "KB", "MB", "GB", "TB");
|
114 |
+
|
115 |
+
$bytes = (double) $bytes;
|
116 |
+
$base = log($bytes) / log(1000); // 1024 would be for MiB KiB etc
|
117 |
+
$pow = pow(1000, $base - floor($base)); // Same rule for 1000
|
118 |
+
|
119 |
+
return round($pow, $precision) . ' ' . $units[(int) floor($base)];
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @param null|string $directories
|
124 |
+
* @param bool $forceDisabled
|
125 |
+
* @return string
|
126 |
+
*/
|
127 |
+
public function directoryListing($directories = null, $forceDisabled = false)
|
128 |
+
{
|
129 |
+
if (null == $directories)
|
130 |
+
{
|
131 |
+
$directories = $this->directories;
|
132 |
+
}
|
133 |
+
|
134 |
+
$output = '';
|
135 |
+
foreach ($directories as $name => $directory)
|
136 |
+
{
|
137 |
+
|
138 |
+
if (!is_array($directory)) {
|
139 |
+
// Not a directory, possibly a symlink, therefore we will skip it
|
140 |
+
continue;
|
141 |
+
}
|
142 |
+
|
143 |
+
// Need to preserve keys so no array_shift()
|
144 |
+
$data = reset($directory);
|
145 |
+
unset($directory[key($directory)]);
|
146 |
+
|
147 |
+
$isChecked = (
|
148 |
+
empty($this->options->includedDirectories) ||
|
149 |
+
in_array($data["path"], $this->options->includedDirectories)
|
150 |
+
);
|
151 |
+
|
152 |
+
$isDisabled = ($this->options->existingClones && isset($this->options->existingClones[$name]));
|
153 |
+
|
154 |
+
$output .= "<div class='wpstg-dir'>";
|
155 |
+
$output .= "<input type='checkbox' class='wpstg-check-dir'";
|
156 |
+
|
157 |
+
if ($isChecked && !$isDisabled && !$forceDisabled) $output .= " checked";
|
158 |
+
if ($forceDisabled || $isDisabled) $output .= " disabled";
|
159 |
+
|
160 |
+
$output .= " name='selectedDirectories[]' value='{$data["path"]}'>";
|
161 |
+
|
162 |
+
$output .= "<a href='#' class='wpstg-expand-dirs";
|
163 |
+
if (!$isChecked || $isDisabled) $output .= " disabled";
|
164 |
+
$output .= "'>{$name}";
|
165 |
+
$output .= "</a>";
|
166 |
+
|
167 |
+
$output .= "<span class='wpstg-size-info'>{$this->formatSize($data["size"])}</span>";
|
168 |
+
|
169 |
+
if (!empty($directory))
|
170 |
+
{
|
171 |
+
$output .= "<div class='wpstg-dir wpstg-subdir'>";
|
172 |
+
$output .= $this->directoryListing($directory, $isDisabled);
|
173 |
+
$output .= "</div>";
|
174 |
+
}
|
175 |
+
|
176 |
+
$output .= "</div>";
|
177 |
+
}
|
178 |
+
|
179 |
+
return $output;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Checks if there is enough free disk space to create staging site
|
184 |
+
* Returns null when can't run disk_free_space function one way or another
|
185 |
+
* @return bool|null
|
186 |
+
*/
|
187 |
+
public function hasFreeDiskSpace() {
|
188 |
+
if( !function_exists( "disk_free_space" ) ) {
|
189 |
+
return null;
|
190 |
+
}
|
191 |
+
|
192 |
+
$freeSpace = @disk_free_space( ABSPATH );
|
193 |
+
|
194 |
+
if( false === $freeSpace ) {
|
195 |
+
$data = array(
|
196 |
+
'freespace' => false,
|
197 |
+
'usedspace' => $this->formatSize($this->getDirectorySizeInclSubdirs(ABSPATH))
|
198 |
+
);
|
199 |
+
echo json_encode($data);
|
200 |
+
die();
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
$data = array(
|
205 |
+
'freespace' => $this->formatSize($freeSpace),
|
206 |
+
'usedspace' => $this->formatSize($this->getDirectorySizeInclSubdirs(ABSPATH))
|
207 |
+
);
|
208 |
+
|
209 |
+
echo json_encode( $data );
|
210 |
+
die();
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Get Database Tables
|
215 |
+
*/
|
216 |
+
protected function getTables()
|
217 |
+
{
|
218 |
+
$wpDB = WPStaging::getInstance()->get("wpdb");
|
219 |
+
|
220 |
+
if (strlen($wpDB->prefix) > 0)
|
221 |
+
{
|
222 |
+
$prefix = str_replace('_', '', $wpDB->prefix);
|
223 |
+
$sql = "SHOW TABLE STATUS LIKE '{$wpDB->prefix}%'";
|
224 |
+
}
|
225 |
+
else
|
226 |
+
{
|
227 |
+
$sql = "SHOW TABLE STATUS";
|
228 |
+
}
|
229 |
+
|
230 |
+
$tables = $wpDB->get_results($sql);
|
231 |
+
|
232 |
+
$currentTables = array();
|
233 |
+
|
234 |
+
// Reset excluded Tables than loop through all tables
|
235 |
+
$this->options->excludedTables = array();
|
236 |
+
foreach ($tables as $table)
|
237 |
+
{
|
238 |
+
|
239 |
+
// Exclude WP Staging Tables
|
240 |
+
// if (0 === strpos($table->Name, "wpstg"))
|
241 |
+
// {
|
242 |
+
// continue;
|
243 |
+
// }
|
244 |
+
// Create array of unchecked tables
|
245 |
+
if (0 !== strpos($table->Name, $wpDB->prefix))
|
246 |
+
{
|
247 |
+
$this->options->excludedTables[] = $table->Name;
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
$currentTables[] = array(
|
252 |
+
"name" => $table->Name,
|
253 |
+
"size" => ($table->Data_length + $table->Index_length)
|
254 |
+
);
|
255 |
+
}
|
256 |
+
|
257 |
+
$this->options->tables = json_decode(json_encode($currentTables));
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Get directories and main meta data about'em recursively
|
262 |
+
*/
|
263 |
+
protected function directories()
|
264 |
+
{
|
265 |
+
$directories = new \DirectoryIterator(ABSPATH);
|
266 |
+
|
267 |
+
foreach($directories as $directory)
|
268 |
+
{
|
269 |
+
// Not a valid directory
|
270 |
+
if (false === ($path = $this->getPath($directory)))
|
271 |
+
{
|
272 |
+
continue;
|
273 |
+
}
|
274 |
+
|
275 |
+
$this->handleDirectory($path);
|
276 |
+
|
277 |
+
// Get Sub-directories
|
278 |
+
$this->getSubDirectories($directory->getRealPath());
|
279 |
+
}
|
280 |
+
|
281 |
+
// Gather Plugins
|
282 |
+
$this->getSubDirectories(WP_PLUGIN_DIR);
|
283 |
+
|
284 |
+
// Gather Themes
|
285 |
+
$this->getSubDirectories(WP_CONTENT_DIR . DIRECTORY_SEPARATOR . "themes");
|
286 |
+
|
287 |
+
// Gather Uploads
|
288 |
+
$this->getSubDirectories(WP_CONTENT_DIR . DIRECTORY_SEPARATOR . "uploads");
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* @param string $path
|
293 |
+
*/
|
294 |
+
protected function getSubDirectories($path)
|
295 |
+
{
|
296 |
+
$directories = new \DirectoryIterator($path);
|
297 |
+
|
298 |
+
foreach($directories as $directory)
|
299 |
+
{
|
300 |
+
// Not a valid directory
|
301 |
+
if (false === ($path = $this->getPath($directory)))
|
302 |
+
{
|
303 |
+
continue;
|
304 |
+
}
|
305 |
+
|
306 |
+
$this->handleDirectory($path);
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Get Path from $directory
|
312 |
+
* @param \SplFileInfo $directory
|
313 |
+
* @return string|false
|
314 |
+
*/
|
315 |
+
protected function getPath($directory)
|
316 |
+
{
|
317 |
+
|
318 |
+
/*
|
319 |
+
* Do not follow root path like src/web/..
|
320 |
+
* This must be done before \SplFileInfo->isDir() is used!
|
321 |
+
* Prevents open base dir restriction fatal errors
|
322 |
+
*/
|
323 |
+
if (strpos( $directory->getRealPath(), ABSPATH ) !== 0 ) {
|
324 |
+
return false;
|
325 |
+
}
|
326 |
+
$path = str_replace(ABSPATH, null, $directory->getRealPath());
|
327 |
+
|
328 |
+
// Using strpos() for symbolic links as they could create nasty stuff in nix stuff for directory structures
|
329 |
+
if (!$directory->isDir() || strlen($path) < 1)
|
330 |
+
{
|
331 |
+
return false;
|
332 |
+
}
|
333 |
+
|
334 |
+
return $path;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Organizes $this->directories
|
339 |
+
* @param string $path
|
340 |
+
*/
|
341 |
+
protected function handleDirectory($path)
|
342 |
+
{
|
343 |
+
$directoryArray = explode(DIRECTORY_SEPARATOR, $path);
|
344 |
+
$total = count($directoryArray);
|
345 |
+
|
346 |
+
if (count($total) < 1)
|
347 |
+
{
|
348 |
+
return;
|
349 |
+
}
|
350 |
+
|
351 |
+
$total = $total - 1;
|
352 |
+
$currentArray = &$this->directories;
|
353 |
+
|
354 |
+
for ($i = 0; $i <= $total; $i++)
|
355 |
+
{
|
356 |
+
if (!isset($currentArray[$directoryArray[$i]]))
|
357 |
+
{
|
358 |
+
$currentArray[$directoryArray[$i]] = array();
|
359 |
+
}
|
360 |
+
|
361 |
+
$currentArray = &$currentArray[$directoryArray[$i]];
|
362 |
+
|
363 |
+
// Attach meta data to the end
|
364 |
+
if ($i < $total)
|
365 |
+
{
|
366 |
+
continue;
|
367 |
+
}
|
368 |
+
|
369 |
+
$fullPath = ABSPATH . $path;
|
370 |
+
$size = $this->getDirectorySize($fullPath);
|
371 |
+
|
372 |
+
$currentArray["metaData"] = array(
|
373 |
+
"size" => $size,
|
374 |
+
"path" => ABSPATH . $path,
|
375 |
+
);
|
376 |
+
}
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Gets size of given directory
|
381 |
+
* @param string $path
|
382 |
+
* @return int|null
|
383 |
+
*/
|
384 |
+
protected function getDirectorySize($path)
|
385 |
+
{
|
386 |
+
if (!isset($this->settings->checkDirectorySize) || '1' !== $this->settings->checkDirectorySize)
|
387 |
+
{
|
388 |
+
return null;
|
389 |
+
}
|
390 |
+
|
391 |
+
return $this->objDirectories->size($path);
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Get total size of a directory including all its subdirectories
|
396 |
+
* @param string $dir
|
397 |
+
* @return int
|
398 |
+
*/
|
399 |
+
function getDirectorySizeInclSubdirs( $dir ) {
|
400 |
+
$size = 0;
|
401 |
+
foreach ( glob( rtrim( $dir, '/' ) . '/*', GLOB_NOSORT ) as $each ) {
|
402 |
+
$size += is_file( $each ) ? filesize( $each ) : $this->getDirectorySizeInclSubdirs( $each );
|
403 |
+
}
|
404 |
+
return $size;
|
405 |
+
}
|
406 |
+
|
407 |
}
|
apps/Backend/Modules/Jobs/Updating.php
CHANGED
@@ -1,262 +1,249 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
-
|
4 |
-
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
-
use WPStaging\WPStaging;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Cloning
|
9 |
-
* @package WPStaging\Backend\Modules\Jobs
|
10 |
-
*/
|
11 |
-
class Updating extends Job
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* Initialize is called in \Job
|
15 |
-
*/
|
16 |
-
public function initialize(){
|
17 |
-
$this->db = WPStaging::getInstance()->get("wpdb");
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Save Chosen Cloning Settings
|
22 |
-
* @return bool
|
23 |
-
*/
|
24 |
-
public function save()
|
25 |
-
{
|
26 |
-
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
27 |
-
{
|
28 |
-
return false;
|
29 |
-
}
|
30 |
-
|
31 |
-
// Generate Options
|
32 |
-
// Clone
|
33 |
-
$this->options->clone = $_POST["cloneID"];
|
34 |
-
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
35 |
-
$this->options->cloneNumber = 1;
|
36 |
-
$this->options->includedDirectories = array();
|
37 |
-
$this->options->excludedDirectories = array();
|
38 |
-
$this->options->extraDirectories = array();
|
39 |
-
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
40 |
-
|
41 |
-
// Job
|
42 |
-
$this->options->job = new \stdClass();
|
43 |
-
|
44 |
-
// Check if clone data already exists and use that one
|
45 |
-
if (isset($this->options->existingClones[$this->options->clone]) )
|
46 |
-
{
|
47 |
-
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]['number'];
|
48 |
-
$this->options->prefix = $this->getStagingPrefix();
|
49 |
-
} else {
|
50 |
-
wp_die('Fatal Error: Can not update clone because there is no clone data.');
|
51 |
-
}
|
52 |
-
|
53 |
-
|
54 |
-
// Excluded Tables
|
55 |
-
if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
56 |
-
{
|
57 |
-
$this->options->excludedTables = $_POST["excludedTables"];
|
58 |
-
}
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
//
|
68 |
-
$excludedDirectories
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
//
|
114 |
-
//
|
115 |
-
|
116 |
-
//
|
117 |
-
|
118 |
-
//
|
119 |
-
|
120 |
-
//
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
if (
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
$data = new Data();
|
250 |
-
return $this->handleJobResponse($data->start(), "finish");
|
251 |
-
}
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Save Clone Data
|
255 |
-
* @return object
|
256 |
-
*/
|
257 |
-
public function jobFinish()
|
258 |
-
{
|
259 |
-
$finish = new Finish();
|
260 |
-
return $this->handleJobResponse($finish->start(), '');
|
261 |
-
}
|
262 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Jobs;
|
3 |
+
|
4 |
+
use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
|
5 |
+
use WPStaging\WPStaging;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Cloning
|
9 |
+
* @package WPStaging\Backend\Modules\Jobs
|
10 |
+
*/
|
11 |
+
class Updating extends Job
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Initialize is called in \Job
|
15 |
+
*/
|
16 |
+
public function initialize(){
|
17 |
+
$this->db = WPStaging::getInstance()->get("wpdb");
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Save Chosen Cloning Settings
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
+
public function save()
|
25 |
+
{
|
26 |
+
if (!isset($_POST) || !isset($_POST["cloneID"]))
|
27 |
+
{
|
28 |
+
return false;
|
29 |
+
}
|
30 |
+
|
31 |
+
// Generate Options
|
32 |
+
// Clone
|
33 |
+
$this->options->clone = $_POST["cloneID"];
|
34 |
+
$this->options->cloneDirectoryName = preg_replace("#\W+#", '-', strtolower($this->options->clone));
|
35 |
+
$this->options->cloneNumber = 1;
|
36 |
+
$this->options->includedDirectories = array();
|
37 |
+
$this->options->excludedDirectories = array();
|
38 |
+
$this->options->extraDirectories = array();
|
39 |
+
$this->options->excludedFiles = array('.htaccess', '.DS_Store', '.git', '.svn', '.tmp', 'desktop.ini', '.gitignore', '.log');
|
40 |
+
|
41 |
+
// Job
|
42 |
+
$this->options->job = new \stdClass();
|
43 |
+
|
44 |
+
// Check if clone data already exists and use that one
|
45 |
+
if (isset($this->options->existingClones[$this->options->clone]) )
|
46 |
+
{
|
47 |
+
$this->options->cloneNumber = $this->options->existingClones[$this->options->clone]['number'];
|
48 |
+
$this->options->prefix = $this->getStagingPrefix();
|
49 |
+
} else {
|
50 |
+
wp_die('Fatal Error: Can not update clone because there is no clone data.');
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
+
// Excluded Tables
|
55 |
+
// if (isset($_POST["excludedTables"]) && is_array($_POST["excludedTables"]))
|
56 |
+
// {
|
57 |
+
// $this->options->excludedTables = $_POST["excludedTables"];
|
58 |
+
// }
|
59 |
+
// Included Tables
|
60 |
+
if (isset($_POST["includedTables"]) && is_array($_POST["includedTables"]))
|
61 |
+
{
|
62 |
+
$this->options->tables = $_POST["includedTables"];
|
63 |
+
} else {
|
64 |
+
$this->options->tables = array();
|
65 |
+
}
|
66 |
+
|
67 |
+
// Excluded Directories
|
68 |
+
if (isset($_POST["excludedDirectories"]) && is_array($_POST["excludedDirectories"]))
|
69 |
+
{
|
70 |
+
$this->options->excludedDirectories = $_POST["excludedDirectories"];
|
71 |
+
}
|
72 |
+
|
73 |
+
// Excluded Directories TOTAL
|
74 |
+
// Do not copy these folders and plugins
|
75 |
+
$excludedDirectories = array(
|
76 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'cache',
|
77 |
+
ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wps-hide-login'
|
78 |
+
);
|
79 |
+
|
80 |
+
$this->options->excludedDirectories = array_merge($excludedDirectories, $this->options->excludedDirectories);
|
81 |
+
|
82 |
+
// Included Directories
|
83 |
+
if (isset($_POST["includedDirectories"]) && is_array($_POST["includedDirectories"]))
|
84 |
+
{
|
85 |
+
$this->options->includedDirectories = $_POST["includedDirectories"];
|
86 |
+
}
|
87 |
+
|
88 |
+
// Extra Directories
|
89 |
+
if (isset($_POST["extraDirectories"]) && !empty($_POST["extraDirectories"]) )
|
90 |
+
{
|
91 |
+
$this->options->extraDirectories = $_POST["extraDirectories"];
|
92 |
+
}
|
93 |
+
|
94 |
+
// Directories to Copy
|
95 |
+
$this->options->directoriesToCopy = array_merge(
|
96 |
+
$this->options->includedDirectories,
|
97 |
+
$this->options->extraDirectories
|
98 |
+
);
|
99 |
+
|
100 |
+
array_unshift($this->options->directoriesToCopy, ABSPATH);
|
101 |
+
|
102 |
+
// Delete files to copy listing
|
103 |
+
$this->cache->delete("files_to_copy");
|
104 |
+
|
105 |
+
return $this->saveOptions();
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Check and return prefix of the staging site
|
111 |
+
*/
|
112 |
+
public function getStagingPrefix() {
|
113 |
+
// prefix not defined! Happens if staging site has ben generated with older version of wpstg
|
114 |
+
// Try to get staging prefix from wp-config.php of staging site
|
115 |
+
$this->options->prefix = $this->options->existingClones[$this->options->clone]['prefix'];
|
116 |
+
//wp_die($this->options->prefix);
|
117 |
+
if (empty($this->options->prefix)) {
|
118 |
+
// Throw error if wp-config.php is not readable
|
119 |
+
$path = ABSPATH . $this->options->cloneDirectoryName . "/wp-config.php";
|
120 |
+
//wp_die($path);
|
121 |
+
if (false === ($content = @file_get_contents($path))) {
|
122 |
+
$this->log("Can not open {$path}. Can't read contents", Logger::TYPE_ERROR);
|
123 |
+
$this->returnException("Fatal Error: Can not read {$path} to get correct table prefix. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
124 |
+
wp_die("Fatal Error: Can not read {$path} to get correct table prefix. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
125 |
+
} else {
|
126 |
+
// Get prefix from wp-config.php
|
127 |
+
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
128 |
+
//wp_die(var_dump($matches));
|
129 |
+
|
130 |
+
if (!empty($matches[1])) {
|
131 |
+
$this->options->prefix = $matches[1];
|
132 |
+
} else {
|
133 |
+
$this->returnException("Fatal Error: Can not detect prefix from {$path}. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
134 |
+
wp_die("Fatal Error: Can not detect prefix from {$path}. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
// Die() if staging prefix is the same as the live prefix
|
140 |
+
if ($this->db->prefix == $this->options->prefix) {
|
141 |
+
$this->log("Fatal Error: Can not updatte staging site. Prefix. '{$this->options->prefix}' is used for the live site. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
142 |
+
wp_die("Fatal Error: Can not update staging site. Prefix. '{$this->options->prefix}' is used for the live site. Stopping for security reasons. Deleting this staging site and creating a new one could fix this issue. Otherwise contact us support@wp-staging.com");
|
143 |
+
}
|
144 |
+
|
145 |
+
// Else
|
146 |
+
//wp_die($this->options->prefix);
|
147 |
+
return $this->options->prefix;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Start the cloning job
|
152 |
+
*/
|
153 |
+
public function start()
|
154 |
+
{
|
155 |
+
if (null === $this->options->currentJob)
|
156 |
+
{
|
157 |
+
$this->log("Cloning job for {$this->options->clone} finished");
|
158 |
+
return true;
|
159 |
+
}
|
160 |
+
|
161 |
+
$methodName = "job" . ucwords($this->options->currentJob);
|
162 |
+
|
163 |
+
if (!method_exists($this, $methodName))
|
164 |
+
{
|
165 |
+
$this->log("Can't execute job; Job's method {$methodName} is not found");
|
166 |
+
throw new JobNotFoundException($methodName);
|
167 |
+
}
|
168 |
+
|
169 |
+
// Call the job
|
170 |
+
//$this->log("execute job: Job's method {$methodName}");
|
171 |
+
return $this->{$methodName}();
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* @param object $response
|
176 |
+
* @param string $nextJob
|
177 |
+
* @return object
|
178 |
+
*/
|
179 |
+
private function handleJobResponse($response, $nextJob)
|
180 |
+
{
|
181 |
+
// Job is not done
|
182 |
+
if (true !== $response->status)
|
183 |
+
{
|
184 |
+
return $response;
|
185 |
+
}
|
186 |
+
|
187 |
+
$this->options->currentJob = $nextJob;
|
188 |
+
$this->options->currentStep = 0;
|
189 |
+
$this->options->totalSteps = 0;
|
190 |
+
|
191 |
+
// Save options
|
192 |
+
$this->saveOptions();
|
193 |
+
|
194 |
+
return $response;
|
195 |
+
}
|
196 |
+
|
197 |
+
|
198 |
+
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Clone Database
|
202 |
+
* @return object
|
203 |
+
*/
|
204 |
+
public function jobDatabase()
|
205 |
+
{
|
206 |
+
$database = new Database();
|
207 |
+
return $this->handleJobResponse($database->start(), "directories");
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Get All Files From Selected Directories Recursively Into a File
|
212 |
+
* @return object
|
213 |
+
*/
|
214 |
+
public function jobDirectories()
|
215 |
+
{
|
216 |
+
$directories = new Directories();
|
217 |
+
return $this->handleJobResponse($directories->start(), "files");
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Copy Files
|
222 |
+
* @return object
|
223 |
+
*/
|
224 |
+
public function jobFiles()
|
225 |
+
{
|
226 |
+
$files = new Files();
|
227 |
+
return $this->handleJobResponse($files->start(), "data");
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Replace Data
|
232 |
+
* @return object
|
233 |
+
*/
|
234 |
+
public function jobData()
|
235 |
+
{
|
236 |
+
$data = new Data();
|
237 |
+
return $this->handleJobResponse($data->start(), "finish");
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Save Clone Data
|
242 |
+
* @return object
|
243 |
+
*/
|
244 |
+
public function jobFinish()
|
245 |
+
{
|
246 |
+
$finish = new Finish();
|
247 |
+
return $this->handleJobResponse($finish->start(), '');
|
248 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
}
|
apps/Backend/Modules/SystemInfo.php
CHANGED
@@ -1,513 +1,513 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules;
|
3 |
-
|
4 |
-
use WPStaging\DI\InjectionAware;
|
5 |
-
use WPStaging\Library\Browser;
|
6 |
-
use WPStaging\WPStaging;
|
7 |
-
|
8 |
-
// No Direct Access
|
9 |
-
if (!defined("WPINC"))
|
10 |
-
{
|
11 |
-
die;
|
12 |
-
}
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class SystemInfo
|
16 |
-
* @package WPStaging\Backend\Modules
|
17 |
-
*/
|
18 |
-
class SystemInfo extends InjectionAware
|
19 |
-
{
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @var bool
|
23 |
-
*/
|
24 |
-
private $isMultiSite;
|
25 |
-
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Initialize class
|
29 |
-
*/
|
30 |
-
public function initialize()
|
31 |
-
{
|
32 |
-
$this->isMultiSite = is_multisite();
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Magic method
|
37 |
-
* @return string
|
38 |
-
*/
|
39 |
-
public function __toString()
|
40 |
-
{
|
41 |
-
return $this->get();
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Get System Information as text
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
public function get()
|
49 |
-
{
|
50 |
-
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
51 |
-
|
52 |
-
$output .= $this->wpstaging();
|
53 |
-
|
54 |
-
$output .= $this->site();
|
55 |
-
|
56 |
-
$output .= $this->browser();
|
57 |
-
|
58 |
-
$output .= $this->wp();
|
59 |
-
|
60 |
-
$output .= $this->plugins();
|
61 |
-
|
62 |
-
$output .= $this->multiSitePlugins();
|
63 |
-
|
64 |
-
$output .= $this->server();
|
65 |
-
|
66 |
-
$output .= $this->php();
|
67 |
-
|
68 |
-
$output .= $this->phpExtensions();
|
69 |
-
|
70 |
-
$output .= PHP_EOL . "### End System Info ###";
|
71 |
-
|
72 |
-
return $output;
|
73 |
-
}
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
/**
|
78 |
-
* @param string $string
|
79 |
-
* @return string
|
80 |
-
*/
|
81 |
-
public function header($string)
|
82 |
-
{
|
83 |
-
return PHP_EOL . "-- {$string}" . PHP_EOL . PHP_EOL;
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Formating title and the value
|
88 |
-
* @param string $title
|
89 |
-
* @param string $value
|
90 |
-
* @return string
|
91 |
-
*/
|
92 |
-
public function info($title, $value)
|
93 |
-
{
|
94 |
-
return str_pad($title, 56, ' ', STR_PAD_RIGHT) . $value . PHP_EOL;
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Theme Information
|
99 |
-
* @return string
|
100 |
-
*/
|
101 |
-
public function theme()
|
102 |
-
{
|
103 |
-
// Versions earlier than 3.4
|
104 |
-
if (get_bloginfo("version") < "3.4" )
|
105 |
-
{
|
106 |
-
$themeData = get_theme_data(get_stylesheet_directory() . "/style.css");
|
107 |
-
return "{$themeData["Name"]} {$themeData["Version"]}";
|
108 |
-
}
|
109 |
-
|
110 |
-
$themeData = wp_get_theme();
|
111 |
-
return "{$themeData->Name} {$themeData->Version}";
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Site Information
|
116 |
-
* @return string
|
117 |
-
*/
|
118 |
-
public function site()
|
119 |
-
{
|
120 |
-
$output = "-- Site Info" . PHP_EOL . PHP_EOL;
|
121 |
-
$output .= $this->info("Site URL:", site_url());
|
122 |
-
$output .= $this->info("Home URL:", home_url());
|
123 |
-
$output .= $this->info("Home Path:", get_home_path());
|
124 |
-
$output .= $this->info("Installed in subdir:", ( $this->isSubDir() ? 'Yes' : 'No' )) ;
|
125 |
-
$output .= $this->info("Multisite:", ($this->isMultiSite ? "Yes" : "No" ));
|
126 |
-
|
127 |
-
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
128 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Wp Staging plugin Information
|
132 |
-
* @return string
|
133 |
-
*/
|
134 |
-
public function wpstaging() {
|
135 |
-
// Get wpstg settings
|
136 |
-
$settings = ( object ) get_option( 'wpstg_settings', array() );
|
137 |
-
|
138 |
-
// Clones data < 1.6.x
|
139 |
-
$clones = ( object ) get_option( 'wpstg_existing_clones', array() );
|
140 |
-
// Clones data version > 2.x
|
141 |
-
$clonesBeta = get_option( 'wpstg_existing_clones_beta' );
|
142 |
-
|
143 |
-
|
144 |
-
$output = "-- WP Staging Settings" . PHP_EOL . PHP_EOL;
|
145 |
-
$output .= $this->info( "Query Limit:", isset( $settings->queryLimit ) ? $settings->queryLimit : 'undefined' );
|
146 |
-
$output .= $this->info( "File Copy Limit:", isset( $settings->fileLimit ) ? $settings->fileLimit : 'undefined' );
|
147 |
-
$output .= $this->info( "Batch Size:", isset( $settings->batchSize ) ? $settings->batchSize : 'undefined' );
|
148 |
-
$output .= $this->info( "CPU Load:", isset( $settings->cpuLoad ) ? $settings->cpuLoad : 'undefined' );
|
149 |
-
$output .= $this->info( "WP in Subdir:", isset( $settings->wpSubDirectory ) ? $settings->wpSubDirectory : 'false' );
|
150 |
-
|
151 |
-
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version < 1.6.x" . PHP_EOL . PHP_EOL;
|
152 |
-
|
153 |
-
$i = 1;
|
154 |
-
foreach ( $clones as $key => $value ) {
|
155 |
-
$output .= $this->info( "Site name & subfolder :", $value );
|
156 |
-
}
|
157 |
-
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version > 2.0.x" . PHP_EOL . PHP_EOL;
|
158 |
-
|
159 |
-
foreach ( $clonesBeta as $key => $clone ) {
|
160 |
-
$output .= $this->info( "Number:", isset( $clone['number'] ) ? $clone['number'] : 'undefined' );
|
161 |
-
$output .= $this->info( "directoryName:", isset( $clone['directoryName'] ) ? $clone['directoryName'] : 'undefined' );
|
162 |
-
$output .= $this->info( "Path:", isset( $clone['path'] ) ? $clone['path'] : 'undefined' );
|
163 |
-
$output .= $this->info( "URL:", isset( $clone['url'] ) ? $clone['url'] : 'undefined' );
|
164 |
-
$output .= $this->info( "DB Prefix:", isset( $clone['prefix'] ) ? $clone['prefix'] : 'undefined' );
|
165 |
-
$output .= $this->info( "DB Prefix wp-config.php:", $this->getStagingPrefix($clone));
|
166 |
-
$output .= $this->info( "Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' ) . PHP_EOL . PHP_EOL;
|
167 |
-
}
|
168 |
-
|
169 |
-
//$output .= PHP_EOL . PHP_EOL;
|
170 |
-
|
171 |
-
$output .= $this->info( "Plugin Version:", get_option('wpstg_version', 'undefined') );
|
172 |
-
$output .= $this->info( "Install Date:", get_option('wpstg_installDate', 'undefined') );
|
173 |
-
$output .= $this->info( "Upgraded from:", get_option('wpstg_version_upgraded_from', 'undefined') );
|
174 |
-
$output .= $this->info( "Is Staging Site:", get_option('wpstg_is_staging_site', 'undefined') ) . PHP_EOL . PHP_EOL;
|
175 |
-
|
176 |
-
|
177 |
-
return apply_filters( "wpstg_sysinfo_after_wpstaging_info", $output );
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* Browser Information
|
182 |
-
* @return string
|
183 |
-
*/
|
184 |
-
public function browser()
|
185 |
-
{
|
186 |
-
$output = $this->header("User Browser");
|
187 |
-
$output .= (new Browser);
|
188 |
-
|
189 |
-
return apply_filters("wpstg_sysinfo_after_user_browser", $output);
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* Frontpage Information when frontpage is set to "page"
|
194 |
-
* @return string
|
195 |
-
*/
|
196 |
-
public function frontPage()
|
197 |
-
{
|
198 |
-
if (get_option("show_on_front") !== "page")
|
199 |
-
{
|
200 |
-
return '';
|
201 |
-
}
|
202 |
-
|
203 |
-
$frontPageID = get_option("page_on_front");
|
204 |
-
$blogPageID = get_option("page_for_posts");
|
205 |
-
|
206 |
-
// Front Page
|
207 |
-
$pageFront = ($frontPageID != 0) ? get_the_title($frontPageID) . " (#{$frontPageID})" : "Unset";
|
208 |
-
// Blog Page ID
|
209 |
-
$pageBlog = ($blogPageID != 0) ? get_the_title($blogPageID) . " (#{$blogPageID})" : "Unset";
|
210 |
-
|
211 |
-
$output = $this->info("Page On Front:", $pageFront);
|
212 |
-
$output .= $this->info("Page For Posts:", $pageBlog);
|
213 |
-
|
214 |
-
return $output;
|
215 |
-
}
|
216 |
-
|
217 |
-
/**
|
218 |
-
* Check wp_remote_post() functionality
|
219 |
-
* @return string
|
220 |
-
*/
|
221 |
-
public function wpRemotePost()
|
222 |
-
{
|
223 |
-
// Make sure wp_remote_post() is working
|
224 |
-
$wpRemotePost = "wp_remote_post() does not work";
|
225 |
-
|
226 |
-
// Send request
|
227 |
-
$response = wp_remote_post(
|
228 |
-
"https://www.paypal.com/cgi-bin/webscr",
|
229 |
-
array(
|
230 |
-
"sslverify" => false,
|
231 |
-
"timeout" => 60,
|
232 |
-
"user-agent" => "WPSTG/" . WPStaging::VERSION,
|
233 |
-
"body" => array("cmd" => "_notify-validate")
|
234 |
-
)
|
235 |
-
);
|
236 |
-
|
237 |
-
// Validate it worked
|
238 |
-
if (!is_wp_error($response) && 200 <= $response["response"]["code"] && 300> $response["response"]["code"])
|
239 |
-
{
|
240 |
-
$wpRemotePost = "wp_remote_post() works";
|
241 |
-
}
|
242 |
-
|
243 |
-
return $this->info("Remote Post:", $wpRemotePost);
|
244 |
-
}
|
245 |
-
|
246 |
-
/**
|
247 |
-
* WordPress Configuration
|
248 |
-
* @return string
|
249 |
-
*/
|
250 |
-
public function wp()
|
251 |
-
{
|
252 |
-
$output = $this->header("WordPress Configuration");
|
253 |
-
$output .= $this->info("Version:", get_bloginfo("version"));
|
254 |
-
$output .= $this->info("Language:", (defined("WPLANG") && WPLANG) ? WPLANG : "en_US");
|
255 |
-
|
256 |
-
$permalinkStructure = get_option("permalink_structure");;
|
257 |
-
$output .= $this->info("Permalink Structure:", ($permalinkStructure) ? $permalinkStructure : "Default");
|
258 |
-
|
259 |
-
$output .= $this->info("Active Theme:", $this->theme());
|
260 |
-
$output .= $this->info("Show On Front:", get_option("show_on_front"));
|
261 |
-
|
262 |
-
// Frontpage information
|
263 |
-
$output .= $this->frontPage();
|
264 |
-
|
265 |
-
// WP Remote Post
|
266 |
-
$output .= $this->wpRemotePost();
|
267 |
-
|
268 |
-
// Table Prefix
|
269 |
-
$wpDB = $this->di->get("wpdb");
|
270 |
-
$tablePrefix = "DB Prefix: " . $wpDB->prefix . ' ';
|
271 |
-
$tablePrefix .= "Length: " . strlen($wpDB->prefix) . " Status: ";
|
272 |
-
$tablePrefix .= (strlen($wpDB->prefix) > 16) ? " ERROR: Too long" : " Acceptable";
|
273 |
-
|
274 |
-
$output .= $this->info("Table Prefix:", $tablePrefix);
|
275 |
-
|
276 |
-
// WP Debug
|
277 |
-
$output .= $this->info("WP_DEBUG:", (defined("WP_DEBUG")) ? WP_DEBUG ? "Enabled" : "Disabled" : "Not set");
|
278 |
-
$output .= $this->info("Memory Limit:", WP_MEMORY_LIMIT);
|
279 |
-
$output .= $this->info("Registered Post Stati:", implode(", ", \get_post_stati()));
|
280 |
-
|
281 |
-
return apply_filters("wpstg_sysinfo_after_wpstg_config", $output);
|
282 |
-
}
|
283 |
-
|
284 |
-
/**
|
285 |
-
* List of Active Plugins
|
286 |
-
* @param array $plugins
|
287 |
-
* @param array $activePlugins
|
288 |
-
* @return string
|
289 |
-
*/
|
290 |
-
public function activePlugins($plugins, $activePlugins)
|
291 |
-
{
|
292 |
-
$output = $this->header("WordPress Active Plugins");
|
293 |
-
|
294 |
-
foreach ($plugins as $path => $plugin)
|
295 |
-
{
|
296 |
-
if (!in_array($path, $activePlugins))
|
297 |
-
{
|
298 |
-
continue;
|
299 |
-
}
|
300 |
-
|
301 |
-
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
302 |
-
}
|
303 |
-
|
304 |
-
return apply_filters("wpstg_sysinfo_after_wordpress_plugins", $output);
|
305 |
-
}
|
306 |
-
|
307 |
-
/**
|
308 |
-
* List of Inactive Plugins
|
309 |
-
* @param array $plugins
|
310 |
-
* @param array $activePlugins
|
311 |
-
* @return string
|
312 |
-
*/
|
313 |
-
public function inactivePlugins($plugins, $activePlugins)
|
314 |
-
{
|
315 |
-
$output = $this->header("WordPress Inactive Plugins");
|
316 |
-
|
317 |
-
foreach ($plugins as $path => $plugin)
|
318 |
-
{
|
319 |
-
if (in_array($path, $activePlugins))
|
320 |
-
{
|
321 |
-
continue;
|
322 |
-
}
|
323 |
-
|
324 |
-
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
325 |
-
}
|
326 |
-
|
327 |
-
return apply_filters("wpstg_sysinfo_after_wordpress_plugins_inactive", $output);
|
328 |
-
}
|
329 |
-
|
330 |
-
/**
|
331 |
-
* Get list of active and inactive plugins
|
332 |
-
* @return string
|
333 |
-
*/
|
334 |
-
public function plugins()
|
335 |
-
{
|
336 |
-
// Get plugins and active plugins
|
337 |
-
$plugins = get_plugins();
|
338 |
-
$activePlugins = get_option("active_plugins", array());
|
339 |
-
|
340 |
-
// Active plugins
|
341 |
-
$output = $this->activePlugins($plugins, $activePlugins);
|
342 |
-
$output .= $this->inactivePlugins($plugins, $activePlugins);
|
343 |
-
|
344 |
-
return $output;
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* Multisite Plugins
|
349 |
-
* @return string
|
350 |
-
*/
|
351 |
-
public function multiSitePlugins()
|
352 |
-
{
|
353 |
-
if (!$this->isMultiSite)
|
354 |
-
{
|
355 |
-
return '';
|
356 |
-
}
|
357 |
-
|
358 |
-
$output = $this->header("Network Active Plugins");
|
359 |
-
|
360 |
-
$plugins = wp_get_active_network_plugins();
|
361 |
-
$activePlugins = get_site_option("active_sitewide_plugins", array());
|
362 |
-
|
363 |
-
foreach ($plugins as $pluginPath)
|
364 |
-
{
|
365 |
-
$pluginBase = plugin_basename($pluginPath);
|
366 |
-
|
367 |
-
if (!array_key_exists($pluginBase, $activePlugins))
|
368 |
-
{
|
369 |
-
continue;
|
370 |
-
}
|
371 |
-
|
372 |
-
$plugin = get_plugin_data($pluginPath);
|
373 |
-
|
374 |
-
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
375 |
-
}
|
376 |
-
unset($plugins, $activePlugins);
|
377 |
-
|
378 |
-
return $output;
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Server Information
|
383 |
-
* @return string
|
384 |
-
*/
|
385 |
-
public function server()
|
386 |
-
{
|
387 |
-
// Server Configuration
|
388 |
-
$output = $this->header("Webserver Configuration");
|
389 |
-
|
390 |
-
$output .= $this->info("PHP Version:", PHP_VERSION);
|
391 |
-
$output .= $this->info("MySQL Version:", $this->di->get("wpdb")->db_version());
|
392 |
-
$output .= $this->info("Webserver Info:", $_SERVER["SERVER_SOFTWARE"]);
|
393 |
-
|
394 |
-
return apply_filters("wpstg_sysinfo_after_webserver_config", $output);
|
395 |
-
}
|
396 |
-
|
397 |
-
/**
|
398 |
-
* PHP Configuration
|
399 |
-
* @return string
|
400 |
-
*/
|
401 |
-
public function php()
|
402 |
-
{
|
403 |
-
$output = $this->header("PHP Configuration");
|
404 |
-
$output .= $this->info("Safe Mode:", ($this->isSafeModeEnabled() ? "Enabled" : "Disabled"));
|
405 |
-
$output .= $this->info("Memory Limit:", ini_get("memory_limit"));
|
406 |
-
$output .= $this->info("Upload Max Size:", ini_get("upload_max_filesize"));
|
407 |
-
$output .= $this->info("Post Max Size:", ini_get("post_max_size"));
|
408 |
-
$output .= $this->info("Upload Max Filesize:", ini_get("upload_max_filesize"));
|
409 |
-
$output .= $this->info("Time Limit:", ini_get("max_execution_time"));
|
410 |
-
$output .= $this->info("Max Input Vars:", ini_get("max_input_vars"));
|
411 |
-
|
412 |
-
$displayErrors = ini_get("display_errors");
|
413 |
-
$output .= $this->info("Display Errors:", ($displayErrors) ? "On ({$displayErrors})" : "N/A");
|
414 |
-
|
415 |
-
return apply_filters("wpstg_sysinfo_after_php_config", $output);
|
416 |
-
}
|
417 |
-
|
418 |
-
/**
|
419 |
-
* Check if PHP is on Safe Mode
|
420 |
-
* @return bool
|
421 |
-
*/
|
422 |
-
public function isSafeModeEnabled()
|
423 |
-
{
|
424 |
-
return (
|
425 |
-
version_compare(PHP_VERSION, "5.4.0", '<') &&
|
426 |
-
@ini_get("safe_mode")
|
427 |
-
);
|
428 |
-
}
|
429 |
-
|
430 |
-
/**
|
431 |
-
* Checks if function exists or not
|
432 |
-
* @param string $functionName
|
433 |
-
* @return string
|
434 |
-
*/
|
435 |
-
public function isSupported($functionName)
|
436 |
-
{
|
437 |
-
return (function_exists($functionName)) ? "Supported" : "Not Supported";
|
438 |
-
}
|
439 |
-
|
440 |
-
/**
|
441 |
-
* Checks if class or extension is loaded / exists to determine if it is installed or not
|
442 |
-
* @param string $name
|
443 |
-
* @param bool $isClass
|
444 |
-
* @return string
|
445 |
-
*/
|
446 |
-
public function isInstalled($name, $isClass = true)
|
447 |
-
{
|
448 |
-
if (true === $isClass)
|
449 |
-
{
|
450 |
-
return (class_exists($name)) ? "Installed" : "Not Installed";
|
451 |
-
}
|
452 |
-
else
|
453 |
-
{
|
454 |
-
return (extension_loaded($name)) ? "Installed" : "Not Installed";
|
455 |
-
}
|
456 |
-
}
|
457 |
-
|
458 |
-
/**
|
459 |
-
* Gets Installed Important PHP Extensions
|
460 |
-
* @return string
|
461 |
-
*/
|
462 |
-
public function phpExtensions()
|
463 |
-
{
|
464 |
-
// Important PHP Extensions
|
465 |
-
$output = $this->header("PHP Extensions");
|
466 |
-
$output .= $this->info("cURL:", $this->isSupported("curl_init"));
|
467 |
-
$output .= $this->info("fsockopen:", $this->isSupported("fsockopen"));
|
468 |
-
$output .= $this->info("SOAP Client:", $this->isInstalled("SoapClient"));
|
469 |
-
$output .= $this->info("Suhosin:", $this->isInstalled("suhosin", false));
|
470 |
-
|
471 |
-
return apply_filters("wpstg_sysinfo_after_php_ext", $output);
|
472 |
-
}
|
473 |
-
|
474 |
-
/**
|
475 |
-
* Check if WP is installed in subdir
|
476 |
-
* @return boolean
|
477 |
-
*/
|
478 |
-
private function isSubDir(){
|
479 |
-
if ( get_option( 'siteurl' ) !== get_option( 'home' ) ) {
|
480 |
-
return true;
|
481 |
-
}
|
482 |
-
return false;
|
483 |
-
}
|
484 |
-
|
485 |
-
/**
|
486 |
-
* Check and return prefix of the staging site
|
487 |
-
*/
|
488 |
-
/**
|
489 |
-
* Try to get the staging prefix from wp-config.php of staging site
|
490 |
-
* @param array $clone
|
491 |
-
* @return sting
|
492 |
-
*/
|
493 |
-
private function getStagingPrefix($clone=array()) {
|
494 |
-
// Throw error
|
495 |
-
$path = ABSPATH . $clone['directoryName'] . "/wp-config.php";
|
496 |
-
if (false === ($content = @file_get_contents($path))) {
|
497 |
-
return 'Can\'t find staging wp-config.php';
|
498 |
-
} else {
|
499 |
-
|
500 |
-
// Get prefix from wp-config.php
|
501 |
-
//preg_match_all("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
502 |
-
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
503 |
-
//wp_die(var_dump($matches));
|
504 |
-
|
505 |
-
if (!empty($matches[1])) {
|
506 |
-
return $matches[1];
|
507 |
-
} else {
|
508 |
-
return 'No table_prefix in wp-config.php';
|
509 |
-
}
|
510 |
-
}
|
511 |
-
|
512 |
-
}
|
513 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules;
|
3 |
+
|
4 |
+
use WPStaging\DI\InjectionAware;
|
5 |
+
use WPStaging\Library\Browser;
|
6 |
+
use WPStaging\WPStaging;
|
7 |
+
|
8 |
+
// No Direct Access
|
9 |
+
if (!defined("WPINC"))
|
10 |
+
{
|
11 |
+
die;
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class SystemInfo
|
16 |
+
* @package WPStaging\Backend\Modules
|
17 |
+
*/
|
18 |
+
class SystemInfo extends InjectionAware
|
19 |
+
{
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var bool
|
23 |
+
*/
|
24 |
+
private $isMultiSite;
|
25 |
+
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Initialize class
|
29 |
+
*/
|
30 |
+
public function initialize()
|
31 |
+
{
|
32 |
+
$this->isMultiSite = is_multisite();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Magic method
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
public function __toString()
|
40 |
+
{
|
41 |
+
return $this->get();
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Get System Information as text
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function get()
|
49 |
+
{
|
50 |
+
$output = "### Begin System Info ###" . PHP_EOL . PHP_EOL;
|
51 |
+
|
52 |
+
$output .= $this->wpstaging();
|
53 |
+
|
54 |
+
$output .= $this->site();
|
55 |
+
|
56 |
+
$output .= $this->browser();
|
57 |
+
|
58 |
+
$output .= $this->wp();
|
59 |
+
|
60 |
+
$output .= $this->plugins();
|
61 |
+
|
62 |
+
$output .= $this->multiSitePlugins();
|
63 |
+
|
64 |
+
$output .= $this->server();
|
65 |
+
|
66 |
+
$output .= $this->php();
|
67 |
+
|
68 |
+
$output .= $this->phpExtensions();
|
69 |
+
|
70 |
+
$output .= PHP_EOL . "### End System Info ###";
|
71 |
+
|
72 |
+
return $output;
|
73 |
+
}
|
74 |
+
|
75 |
+
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @param string $string
|
79 |
+
* @return string
|
80 |
+
*/
|
81 |
+
public function header($string)
|
82 |
+
{
|
83 |
+
return PHP_EOL . "-- {$string}" . PHP_EOL . PHP_EOL;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Formating title and the value
|
88 |
+
* @param string $title
|
89 |
+
* @param string $value
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
public function info($title, $value)
|
93 |
+
{
|
94 |
+
return str_pad($title, 56, ' ', STR_PAD_RIGHT) . $value . PHP_EOL;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Theme Information
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function theme()
|
102 |
+
{
|
103 |
+
// Versions earlier than 3.4
|
104 |
+
if (get_bloginfo("version") < "3.4" )
|
105 |
+
{
|
106 |
+
$themeData = get_theme_data(get_stylesheet_directory() . "/style.css");
|
107 |
+
return "{$themeData["Name"]} {$themeData["Version"]}";
|
108 |
+
}
|
109 |
+
|
110 |
+
$themeData = wp_get_theme();
|
111 |
+
return "{$themeData->Name} {$themeData->Version}";
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Site Information
|
116 |
+
* @return string
|
117 |
+
*/
|
118 |
+
public function site()
|
119 |
+
{
|
120 |
+
$output = "-- Site Info" . PHP_EOL . PHP_EOL;
|
121 |
+
$output .= $this->info("Site URL:", site_url());
|
122 |
+
$output .= $this->info("Home URL:", home_url());
|
123 |
+
$output .= $this->info("Home Path:", get_home_path());
|
124 |
+
$output .= $this->info("Installed in subdir:", ( $this->isSubDir() ? 'Yes' : 'No' )) ;
|
125 |
+
$output .= $this->info("Multisite:", ($this->isMultiSite ? "Yes" : "No" ));
|
126 |
+
|
127 |
+
return apply_filters("wpstg_sysinfo_after_site_info", $output);
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Wp Staging plugin Information
|
132 |
+
* @return string
|
133 |
+
*/
|
134 |
+
public function wpstaging() {
|
135 |
+
// Get wpstg settings
|
136 |
+
$settings = ( object ) get_option( 'wpstg_settings', array() );
|
137 |
+
|
138 |
+
// Clones data < 1.6.x
|
139 |
+
$clones = ( object ) get_option( 'wpstg_existing_clones', array() );
|
140 |
+
// Clones data version > 2.x
|
141 |
+
$clonesBeta = get_option( 'wpstg_existing_clones_beta' );
|
142 |
+
|
143 |
+
|
144 |
+
$output = "-- WP Staging Settings" . PHP_EOL . PHP_EOL;
|
145 |
+
$output .= $this->info( "Query Limit:", isset( $settings->queryLimit ) ? $settings->queryLimit : 'undefined' );
|
146 |
+
$output .= $this->info( "File Copy Limit:", isset( $settings->fileLimit ) ? $settings->fileLimit : 'undefined' );
|
147 |
+
$output .= $this->info( "Batch Size:", isset( $settings->batchSize ) ? $settings->batchSize : 'undefined' );
|
148 |
+
$output .= $this->info( "CPU Load:", isset( $settings->cpuLoad ) ? $settings->cpuLoad : 'undefined' );
|
149 |
+
$output .= $this->info( "WP in Subdir:", isset( $settings->wpSubDirectory ) ? $settings->wpSubDirectory : 'false' );
|
150 |
+
|
151 |
+
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version < 1.6.x" . PHP_EOL . PHP_EOL;
|
152 |
+
|
153 |
+
$i = 1;
|
154 |
+
foreach ( $clones as $key => $value ) {
|
155 |
+
$output .= $this->info( "Site name & subfolder :", $value );
|
156 |
+
}
|
157 |
+
$output .= PHP_EOL . PHP_EOL . "-- Available Sites Version > 2.0.x" . PHP_EOL . PHP_EOL;
|
158 |
+
|
159 |
+
foreach ( $clonesBeta as $key => $clone ) {
|
160 |
+
$output .= $this->info( "Number:", isset( $clone['number'] ) ? $clone['number'] : 'undefined' );
|
161 |
+
$output .= $this->info( "directoryName:", isset( $clone['directoryName'] ) ? $clone['directoryName'] : 'undefined' );
|
162 |
+
$output .= $this->info( "Path:", isset( $clone['path'] ) ? $clone['path'] : 'undefined' );
|
163 |
+
$output .= $this->info( "URL:", isset( $clone['url'] ) ? $clone['url'] : 'undefined' );
|
164 |
+
$output .= $this->info( "DB Prefix:", isset( $clone['prefix'] ) ? $clone['prefix'] : 'undefined' );
|
165 |
+
$output .= $this->info( "DB Prefix wp-config.php:", $this->getStagingPrefix($clone));
|
166 |
+
$output .= $this->info( "Version:", isset( $clone['version'] ) ? $clone['version'] : 'undefined' ) . PHP_EOL . PHP_EOL;
|
167 |
+
}
|
168 |
+
|
169 |
+
//$output .= PHP_EOL . PHP_EOL;
|
170 |
+
|
171 |
+
$output .= $this->info( "Plugin Version:", get_option('wpstg_version', 'undefined') );
|
172 |
+
$output .= $this->info( "Install Date:", get_option('wpstg_installDate', 'undefined') );
|
173 |
+
$output .= $this->info( "Upgraded from:", get_option('wpstg_version_upgraded_from', 'undefined') );
|
174 |
+
$output .= $this->info( "Is Staging Site:", get_option('wpstg_is_staging_site', 'undefined') ) . PHP_EOL . PHP_EOL;
|
175 |
+
|
176 |
+
|
177 |
+
return apply_filters( "wpstg_sysinfo_after_wpstaging_info", $output );
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Browser Information
|
182 |
+
* @return string
|
183 |
+
*/
|
184 |
+
public function browser()
|
185 |
+
{
|
186 |
+
$output = $this->header("User Browser");
|
187 |
+
$output .= (new Browser);
|
188 |
+
|
189 |
+
return apply_filters("wpstg_sysinfo_after_user_browser", $output);
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Frontpage Information when frontpage is set to "page"
|
194 |
+
* @return string
|
195 |
+
*/
|
196 |
+
public function frontPage()
|
197 |
+
{
|
198 |
+
if (get_option("show_on_front") !== "page")
|
199 |
+
{
|
200 |
+
return '';
|
201 |
+
}
|
202 |
+
|
203 |
+
$frontPageID = get_option("page_on_front");
|
204 |
+
$blogPageID = get_option("page_for_posts");
|
205 |
+
|
206 |
+
// Front Page
|
207 |
+
$pageFront = ($frontPageID != 0) ? get_the_title($frontPageID) . " (#{$frontPageID})" : "Unset";
|
208 |
+
// Blog Page ID
|
209 |
+
$pageBlog = ($blogPageID != 0) ? get_the_title($blogPageID) . " (#{$blogPageID})" : "Unset";
|
210 |
+
|
211 |
+
$output = $this->info("Page On Front:", $pageFront);
|
212 |
+
$output .= $this->info("Page For Posts:", $pageBlog);
|
213 |
+
|
214 |
+
return $output;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Check wp_remote_post() functionality
|
219 |
+
* @return string
|
220 |
+
*/
|
221 |
+
public function wpRemotePost()
|
222 |
+
{
|
223 |
+
// Make sure wp_remote_post() is working
|
224 |
+
$wpRemotePost = "wp_remote_post() does not work";
|
225 |
+
|
226 |
+
// Send request
|
227 |
+
$response = wp_remote_post(
|
228 |
+
"https://www.paypal.com/cgi-bin/webscr",
|
229 |
+
array(
|
230 |
+
"sslverify" => false,
|
231 |
+
"timeout" => 60,
|
232 |
+
"user-agent" => "WPSTG/" . WPStaging::VERSION,
|
233 |
+
"body" => array("cmd" => "_notify-validate")
|
234 |
+
)
|
235 |
+
);
|
236 |
+
|
237 |
+
// Validate it worked
|
238 |
+
if (!is_wp_error($response) && 200 <= $response["response"]["code"] && 300> $response["response"]["code"])
|
239 |
+
{
|
240 |
+
$wpRemotePost = "wp_remote_post() works";
|
241 |
+
}
|
242 |
+
|
243 |
+
return $this->info("Remote Post:", $wpRemotePost);
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* WordPress Configuration
|
248 |
+
* @return string
|
249 |
+
*/
|
250 |
+
public function wp()
|
251 |
+
{
|
252 |
+
$output = $this->header("WordPress Configuration");
|
253 |
+
$output .= $this->info("Version:", get_bloginfo("version"));
|
254 |
+
$output .= $this->info("Language:", (defined("WPLANG") && WPLANG) ? WPLANG : "en_US");
|
255 |
+
|
256 |
+
$permalinkStructure = get_option("permalink_structure");;
|
257 |
+
$output .= $this->info("Permalink Structure:", ($permalinkStructure) ? $permalinkStructure : "Default");
|
258 |
+
|
259 |
+
$output .= $this->info("Active Theme:", $this->theme());
|
260 |
+
$output .= $this->info("Show On Front:", get_option("show_on_front"));
|
261 |
+
|
262 |
+
// Frontpage information
|
263 |
+
$output .= $this->frontPage();
|
264 |
+
|
265 |
+
// WP Remote Post
|
266 |
+
$output .= $this->wpRemotePost();
|
267 |
+
|
268 |
+
// Table Prefix
|
269 |
+
$wpDB = $this->di->get("wpdb");
|
270 |
+
$tablePrefix = "DB Prefix: " . $wpDB->prefix . ' ';
|
271 |
+
$tablePrefix .= "Length: " . strlen($wpDB->prefix) . " Status: ";
|
272 |
+
$tablePrefix .= (strlen($wpDB->prefix) > 16) ? " ERROR: Too long" : " Acceptable";
|
273 |
+
|
274 |
+
$output .= $this->info("Table Prefix:", $tablePrefix);
|
275 |
+
|
276 |
+
// WP Debug
|
277 |
+
$output .= $this->info("WP_DEBUG:", (defined("WP_DEBUG")) ? WP_DEBUG ? "Enabled" : "Disabled" : "Not set");
|
278 |
+
$output .= $this->info("Memory Limit:", WP_MEMORY_LIMIT);
|
279 |
+
$output .= $this->info("Registered Post Stati:", implode(", ", \get_post_stati()));
|
280 |
+
|
281 |
+
return apply_filters("wpstg_sysinfo_after_wpstg_config", $output);
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* List of Active Plugins
|
286 |
+
* @param array $plugins
|
287 |
+
* @param array $activePlugins
|
288 |
+
* @return string
|
289 |
+
*/
|
290 |
+
public function activePlugins($plugins, $activePlugins)
|
291 |
+
{
|
292 |
+
$output = $this->header("WordPress Active Plugins");
|
293 |
+
|
294 |
+
foreach ($plugins as $path => $plugin)
|
295 |
+
{
|
296 |
+
if (!in_array($path, $activePlugins))
|
297 |
+
{
|
298 |
+
continue;
|
299 |
+
}
|
300 |
+
|
301 |
+
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
302 |
+
}
|
303 |
+
|
304 |
+
return apply_filters("wpstg_sysinfo_after_wordpress_plugins", $output);
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* List of Inactive Plugins
|
309 |
+
* @param array $plugins
|
310 |
+
* @param array $activePlugins
|
311 |
+
* @return string
|
312 |
+
*/
|
313 |
+
public function inactivePlugins($plugins, $activePlugins)
|
314 |
+
{
|
315 |
+
$output = $this->header("WordPress Inactive Plugins");
|
316 |
+
|
317 |
+
foreach ($plugins as $path => $plugin)
|
318 |
+
{
|
319 |
+
if (in_array($path, $activePlugins))
|
320 |
+
{
|
321 |
+
continue;
|
322 |
+
}
|
323 |
+
|
324 |
+
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
325 |
+
}
|
326 |
+
|
327 |
+
return apply_filters("wpstg_sysinfo_after_wordpress_plugins_inactive", $output);
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Get list of active and inactive plugins
|
332 |
+
* @return string
|
333 |
+
*/
|
334 |
+
public function plugins()
|
335 |
+
{
|
336 |
+
// Get plugins and active plugins
|
337 |
+
$plugins = get_plugins();
|
338 |
+
$activePlugins = get_option("active_plugins", array());
|
339 |
+
|
340 |
+
// Active plugins
|
341 |
+
$output = $this->activePlugins($plugins, $activePlugins);
|
342 |
+
$output .= $this->inactivePlugins($plugins, $activePlugins);
|
343 |
+
|
344 |
+
return $output;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Multisite Plugins
|
349 |
+
* @return string
|
350 |
+
*/
|
351 |
+
public function multiSitePlugins()
|
352 |
+
{
|
353 |
+
if (!$this->isMultiSite)
|
354 |
+
{
|
355 |
+
return '';
|
356 |
+
}
|
357 |
+
|
358 |
+
$output = $this->header("Network Active Plugins");
|
359 |
+
|
360 |
+
$plugins = wp_get_active_network_plugins();
|
361 |
+
$activePlugins = get_site_option("active_sitewide_plugins", array());
|
362 |
+
|
363 |
+
foreach ($plugins as $pluginPath)
|
364 |
+
{
|
365 |
+
$pluginBase = plugin_basename($pluginPath);
|
366 |
+
|
367 |
+
if (!array_key_exists($pluginBase, $activePlugins))
|
368 |
+
{
|
369 |
+
continue;
|
370 |
+
}
|
371 |
+
|
372 |
+
$plugin = get_plugin_data($pluginPath);
|
373 |
+
|
374 |
+
$output .= "{$plugin["Name"]}: {$plugin["Version"]}" . PHP_EOL;
|
375 |
+
}
|
376 |
+
unset($plugins, $activePlugins);
|
377 |
+
|
378 |
+
return $output;
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Server Information
|
383 |
+
* @return string
|
384 |
+
*/
|
385 |
+
public function server()
|
386 |
+
{
|
387 |
+
// Server Configuration
|
388 |
+
$output = $this->header("Webserver Configuration");
|
389 |
+
|
390 |
+
$output .= $this->info("PHP Version:", PHP_VERSION);
|
391 |
+
$output .= $this->info("MySQL Version:", $this->di->get("wpdb")->db_version());
|
392 |
+
$output .= $this->info("Webserver Info:", $_SERVER["SERVER_SOFTWARE"]);
|
393 |
+
|
394 |
+
return apply_filters("wpstg_sysinfo_after_webserver_config", $output);
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* PHP Configuration
|
399 |
+
* @return string
|
400 |
+
*/
|
401 |
+
public function php()
|
402 |
+
{
|
403 |
+
$output = $this->header("PHP Configuration");
|
404 |
+
$output .= $this->info("Safe Mode:", ($this->isSafeModeEnabled() ? "Enabled" : "Disabled"));
|
405 |
+
$output .= $this->info("Memory Limit:", ini_get("memory_limit"));
|
406 |
+
$output .= $this->info("Upload Max Size:", ini_get("upload_max_filesize"));
|
407 |
+
$output .= $this->info("Post Max Size:", ini_get("post_max_size"));
|
408 |
+
$output .= $this->info("Upload Max Filesize:", ini_get("upload_max_filesize"));
|
409 |
+
$output .= $this->info("Time Limit:", ini_get("max_execution_time"));
|
410 |
+
$output .= $this->info("Max Input Vars:", ini_get("max_input_vars"));
|
411 |
+
|
412 |
+
$displayErrors = ini_get("display_errors");
|
413 |
+
$output .= $this->info("Display Errors:", ($displayErrors) ? "On ({$displayErrors})" : "N/A");
|
414 |
+
|
415 |
+
return apply_filters("wpstg_sysinfo_after_php_config", $output);
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Check if PHP is on Safe Mode
|
420 |
+
* @return bool
|
421 |
+
*/
|
422 |
+
public function isSafeModeEnabled()
|
423 |
+
{
|
424 |
+
return (
|
425 |
+
version_compare(PHP_VERSION, "5.4.0", '<') &&
|
426 |
+
@ini_get("safe_mode")
|
427 |
+
);
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Checks if function exists or not
|
432 |
+
* @param string $functionName
|
433 |
+
* @return string
|
434 |
+
*/
|
435 |
+
public function isSupported($functionName)
|
436 |
+
{
|
437 |
+
return (function_exists($functionName)) ? "Supported" : "Not Supported";
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Checks if class or extension is loaded / exists to determine if it is installed or not
|
442 |
+
* @param string $name
|
443 |
+
* @param bool $isClass
|
444 |
+
* @return string
|
445 |
+
*/
|
446 |
+
public function isInstalled($name, $isClass = true)
|
447 |
+
{
|
448 |
+
if (true === $isClass)
|
449 |
+
{
|
450 |
+
return (class_exists($name)) ? "Installed" : "Not Installed";
|
451 |
+
}
|
452 |
+
else
|
453 |
+
{
|
454 |
+
return (extension_loaded($name)) ? "Installed" : "Not Installed";
|
455 |
+
}
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Gets Installed Important PHP Extensions
|
460 |
+
* @return string
|
461 |
+
*/
|
462 |
+
public function phpExtensions()
|
463 |
+
{
|
464 |
+
// Important PHP Extensions
|
465 |
+
$output = $this->header("PHP Extensions");
|
466 |
+
$output .= $this->info("cURL:", $this->isSupported("curl_init"));
|
467 |
+
$output .= $this->info("fsockopen:", $this->isSupported("fsockopen"));
|
468 |
+
$output .= $this->info("SOAP Client:", $this->isInstalled("SoapClient"));
|
469 |
+
$output .= $this->info("Suhosin:", $this->isInstalled("suhosin", false));
|
470 |
+
|
471 |
+
return apply_filters("wpstg_sysinfo_after_php_ext", $output);
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Check if WP is installed in subdir
|
476 |
+
* @return boolean
|
477 |
+
*/
|
478 |
+
private function isSubDir(){
|
479 |
+
if ( get_option( 'siteurl' ) !== get_option( 'home' ) ) {
|
480 |
+
return true;
|
481 |
+
}
|
482 |
+
return false;
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Check and return prefix of the staging site
|
487 |
+
*/
|
488 |
+
/**
|
489 |
+
* Try to get the staging prefix from wp-config.php of staging site
|
490 |
+
* @param array $clone
|
491 |
+
* @return sting
|
492 |
+
*/
|
493 |
+
private function getStagingPrefix($clone=array()) {
|
494 |
+
// Throw error
|
495 |
+
$path = ABSPATH . $clone['directoryName'] . "/wp-config.php";
|
496 |
+
if (false === ($content = @file_get_contents($path))) {
|
497 |
+
return 'Can\'t find staging wp-config.php';
|
498 |
+
} else {
|
499 |
+
|
500 |
+
// Get prefix from wp-config.php
|
501 |
+
//preg_match_all("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
502 |
+
preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
|
503 |
+
//wp_die(var_dump($matches));
|
504 |
+
|
505 |
+
if (!empty($matches[1])) {
|
506 |
+
return $matches[1];
|
507 |
+
} else {
|
508 |
+
return 'No table_prefix in wp-config.php';
|
509 |
+
}
|
510 |
+
}
|
511 |
+
|
512 |
+
}
|
513 |
}
|
apps/Backend/Modules/Views/Forms/Settings.php
CHANGED
@@ -1,220 +1,220 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Backend\Modules\Views\Forms;
|
3 |
-
|
4 |
-
use WPStaging\Forms\Elements\Check;
|
5 |
-
use WPStaging\Forms\Elements\Numerical;
|
6 |
-
use WPStaging\Forms\Elements\Select;
|
7 |
-
use WPStaging\Forms\Elements\SelectMultiple;
|
8 |
-
use WPStaging\Forms\Form;
|
9 |
-
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Class Settings
|
13 |
-
* @package WPStaging\Backend\Modules\Views\Forms
|
14 |
-
*/
|
15 |
-
class Settings
|
16 |
-
{
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @var array
|
20 |
-
*/
|
21 |
-
private $form = array();
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @var Tabs
|
25 |
-
*/
|
26 |
-
private $tabs;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Settings constructor.
|
30 |
-
* @param Tabs $tabs
|
31 |
-
*/
|
32 |
-
public function __construct($tabs)
|
33 |
-
{
|
34 |
-
$this->tabs = $tabs;
|
35 |
-
|
36 |
-
foreach ($this->tabs->get() as $id => $name)
|
37 |
-
{
|
38 |
-
if (!method_exists($this, $id))
|
39 |
-
{
|
40 |
-
continue;
|
41 |
-
}
|
42 |
-
|
43 |
-
$this->{$id}();
|
44 |
-
}
|
45 |
-
}
|
46 |
-
|
47 |
-
private function general()
|
48 |
-
{
|
49 |
-
$this->form["general"] = new Form();
|
50 |
-
|
51 |
-
$settings = json_decode(json_encode(get_option("wpstg_settings", array())));
|
52 |
-
|
53 |
-
// DB Copy Query Limit
|
54 |
-
$element = new Numerical(
|
55 |
-
"wpstg_settings[queryLimit]",
|
56 |
-
array(
|
57 |
-
"class" => "medium-text",
|
58 |
-
"step" => 1,
|
59 |
-
"max" => 999999,
|
60 |
-
"min" => 0
|
61 |
-
)
|
62 |
-
);
|
63 |
-
|
64 |
-
$this->form["general"]->add(
|
65 |
-
$element->setLabel("DB Copy Query Limit")
|
66 |
-
->setDefault(isset($settings->queryLimit) ? $settings->queryLimit :
|
67 |
-
);
|
68 |
-
|
69 |
-
$options = array('1' => '1', '250' => '250' ,'500' => '500', '1000' => '1000');
|
70 |
-
// DB Copy Query Limit
|
71 |
-
$element = new Select(
|
72 |
-
"wpstg_settings[fileLimit]",
|
73 |
-
$options,
|
74 |
-
array(
|
75 |
-
"class" => "medium-text",
|
76 |
-
"step" => 1,
|
77 |
-
"max" => 999999,
|
78 |
-
"min" => 0
|
79 |
-
)
|
80 |
-
);
|
81 |
-
|
82 |
-
$this->form["general"]->add(
|
83 |
-
$element->setLabel("File Copy Limit")->setDefault(isset($settings->fileLimit) ? $settings->fileLimit : 250)
|
84 |
-
);
|
85 |
-
|
86 |
-
|
87 |
-
// File Copy Batch Size
|
88 |
-
$element = new Numerical(
|
89 |
-
"wpstg_settings[batchSize]",
|
90 |
-
array(
|
91 |
-
"class" => "medium-text",
|
92 |
-
"step" => 1,
|
93 |
-
"max" => 999999,
|
94 |
-
"min" => 0
|
95 |
-
)
|
96 |
-
);
|
97 |
-
|
98 |
-
$this->form["general"]->add(
|
99 |
-
$element->setLabel("File Copy Batch Size")
|
100 |
-
->setDefault(isset($settings->batchSize) ? $settings->batchSize : 2)
|
101 |
-
);
|
102 |
-
|
103 |
-
// CPU load priority
|
104 |
-
$element = new Select(
|
105 |
-
"wpstg_settings[cpuLoad]",
|
106 |
-
array(
|
107 |
-
"high" => "High (fast)",
|
108 |
-
"medium" => "Medium (average)",
|
109 |
-
"low" => "Low (slow)"
|
110 |
-
)
|
111 |
-
);
|
112 |
-
|
113 |
-
$this->form["general"]->add(
|
114 |
-
$element->setLabel("CPU load priority")
|
115 |
-
->setDefault(isset($settings->cpuLoad) ? $settings->cpuLoad : "fast")
|
116 |
-
);
|
117 |
-
|
118 |
-
|
119 |
-
// Optimizer
|
120 |
-
$element = new Check(
|
121 |
-
"wpstg_settings[optimizer]",
|
122 |
-
array('1' => "Select the plugins you wish to disable during clone process")
|
123 |
-
);
|
124 |
-
|
125 |
-
$this->form["general"]->add(
|
126 |
-
$element->setLabel("Optimizer")
|
127 |
-
->setDefault((isset($settings->optimizer)) ? $settings->optimizer : null)
|
128 |
-
);
|
129 |
-
|
130 |
-
// Plugins
|
131 |
-
$plugins = array();
|
132 |
-
|
133 |
-
foreach (get_plugins() as $key => $data)
|
134 |
-
{
|
135 |
-
if ("wp-staging/wp-staging.php" === $key)
|
136 |
-
{
|
137 |
-
continue;
|
138 |
-
}
|
139 |
-
|
140 |
-
$plugins[$key] = $data["Name"];
|
141 |
-
}
|
142 |
-
|
143 |
-
$element = new Select(
|
144 |
-
"wpstg_settings[blackListedPlugins][]",
|
145 |
-
$plugins,
|
146 |
-
array(
|
147 |
-
"multiple" => "multiple",
|
148 |
-
"style" => "min-height:400px;"
|
149 |
-
)
|
150 |
-
);
|
151 |
-
|
152 |
-
$this->form["general"]->add(
|
153 |
-
$element->setDefault((isset($settings->blackListedPlugins)) ? $settings->blackListedPlugins : null)
|
154 |
-
);
|
155 |
-
|
156 |
-
// Disable admin authorization
|
157 |
-
$element = new Check(
|
158 |
-
"wpstg_settings[disableAdminLogin]",
|
159 |
-
array('1' => '')
|
160 |
-
);
|
161 |
-
|
162 |
-
$this->form["general"]->add(
|
163 |
-
$element->setLabel("Disable admin authorization")
|
164 |
-
->setDefault((isset($settings->disableAdminLogin)) ? $settings->disableAdminLogin : null)
|
165 |
-
);
|
166 |
-
|
167 |
-
// WordPress in subdirectory
|
168 |
-
$element = new Check(
|
169 |
-
"wpstg_settings[wpSubDirectory]",
|
170 |
-
array('1' => '')
|
171 |
-
);
|
172 |
-
|
173 |
-
$this->form["general"]->add(
|
174 |
-
$element->setLabel("Wordpress in subdirectory")
|
175 |
-
->setDefault((isset($settings->wpSubDirectory)) ? $settings->wpSubDirectory : null)
|
176 |
-
);
|
177 |
-
|
178 |
-
// Debug Mode
|
179 |
-
$element = new Check(
|
180 |
-
"wpstg_settings[debugMode]",
|
181 |
-
array('1' => '')
|
182 |
-
);
|
183 |
-
|
184 |
-
$this->form["general"]->add(
|
185 |
-
$element->setLabel("Debug Mode")
|
186 |
-
->setDefault((isset($settings->debugMode)) ? $settings->debugMode : null)
|
187 |
-
);
|
188 |
-
|
189 |
-
// Remove Data on Uninstall?
|
190 |
-
$element = new Check(
|
191 |
-
"wpstg_settings[unInstallOnDelete]",
|
192 |
-
array('1' => '')
|
193 |
-
);
|
194 |
-
|
195 |
-
$this->form["general"]->add(
|
196 |
-
$element->setLabel("Remove Data on Uninstall?")
|
197 |
-
->setDefault((isset($settings->unInstallOnDelete)) ? $settings->unInstallOnDelete : null)
|
198 |
-
);
|
199 |
-
|
200 |
-
// Check Directory Sizes
|
201 |
-
$element = new Check(
|
202 |
-
"wpstg_settings[checkDirectorySize]",
|
203 |
-
array('1' => '')
|
204 |
-
);
|
205 |
-
|
206 |
-
$this->form["general"]->add(
|
207 |
-
$element->setLabel("Check Directory Size")
|
208 |
-
->setDefault((isset($settings->checkDirectorySize)) ? $settings->checkDirectorySize : null)
|
209 |
-
);
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* @param string $name
|
214 |
-
* @return array|Form
|
215 |
-
*/
|
216 |
-
public function get($name = null)
|
217 |
-
{
|
218 |
-
return (null === $name) ? $this->form : $this->form[$name];
|
219 |
-
}
|
220 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Backend\Modules\Views\Forms;
|
3 |
+
|
4 |
+
use WPStaging\Forms\Elements\Check;
|
5 |
+
use WPStaging\Forms\Elements\Numerical;
|
6 |
+
use WPStaging\Forms\Elements\Select;
|
7 |
+
use WPStaging\Forms\Elements\SelectMultiple;
|
8 |
+
use WPStaging\Forms\Form;
|
9 |
+
use WPStaging\Backend\Modules\Views\Tabs\Tabs;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Class Settings
|
13 |
+
* @package WPStaging\Backend\Modules\Views\Forms
|
14 |
+
*/
|
15 |
+
class Settings
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var array
|
20 |
+
*/
|
21 |
+
private $form = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var Tabs
|
25 |
+
*/
|
26 |
+
private $tabs;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Settings constructor.
|
30 |
+
* @param Tabs $tabs
|
31 |
+
*/
|
32 |
+
public function __construct($tabs)
|
33 |
+
{
|
34 |
+
$this->tabs = $tabs;
|
35 |
+
|
36 |
+
foreach ($this->tabs->get() as $id => $name)
|
37 |
+
{
|
38 |
+
if (!method_exists($this, $id))
|
39 |
+
{
|
40 |
+
continue;
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->{$id}();
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
private function general()
|
48 |
+
{
|
49 |
+
$this->form["general"] = new Form();
|
50 |
+
|
51 |
+
$settings = json_decode(json_encode(get_option("wpstg_settings", array())));
|
52 |
+
|
53 |
+
// DB Copy Query Limit
|
54 |
+
$element = new Numerical(
|
55 |
+
"wpstg_settings[queryLimit]",
|
56 |
+
array(
|
57 |
+
"class" => "medium-text",
|
58 |
+
"step" => 1,
|
59 |
+
"max" => 999999,
|
60 |
+
"min" => 0
|
61 |
+
)
|
62 |
+
);
|
63 |
+
|
64 |
+
$this->form["general"]->add(
|
65 |
+
$element->setLabel("DB Copy Query Limit")
|
66 |
+
->setDefault(isset($settings->queryLimit) ? $settings->queryLimit : 5000)
|
67 |
+
);
|
68 |
+
|
69 |
+
$options = array('1' => '1', '250' => '250' ,'500' => '500', '1000' => '1000');
|
70 |
+
// DB Copy Query Limit
|
71 |
+
$element = new Select(
|
72 |
+
"wpstg_settings[fileLimit]",
|
73 |
+
$options,
|
74 |
+
array(
|
75 |
+
"class" => "medium-text",
|
76 |
+
"step" => 1,
|
77 |
+
"max" => 999999,
|
78 |
+
"min" => 0
|
79 |
+
)
|
80 |
+
);
|
81 |
+
|
82 |
+
$this->form["general"]->add(
|
83 |
+
$element->setLabel("File Copy Limit")->setDefault(isset($settings->fileLimit) ? $settings->fileLimit : 250)
|
84 |
+
);
|
85 |
+
|
86 |
+
|
87 |
+
// File Copy Batch Size
|
88 |
+
$element = new Numerical(
|
89 |
+
"wpstg_settings[batchSize]",
|
90 |
+
array(
|
91 |
+
"class" => "medium-text",
|
92 |
+
"step" => 1,
|
93 |
+
"max" => 999999,
|
94 |
+
"min" => 0
|
95 |
+
)
|
96 |
+
);
|
97 |
+
|
98 |
+
$this->form["general"]->add(
|
99 |
+
$element->setLabel("File Copy Batch Size")
|
100 |
+
->setDefault(isset($settings->batchSize) ? $settings->batchSize : 2)
|
101 |
+
);
|
102 |
+
|
103 |
+
// CPU load priority
|
104 |
+
$element = new Select(
|
105 |
+
"wpstg_settings[cpuLoad]",
|
106 |
+
array(
|
107 |
+
"high" => "High (fast)",
|
108 |
+
"medium" => "Medium (average)",
|
109 |
+
"low" => "Low (slow)"
|
110 |
+
)
|
111 |
+
);
|
112 |
+
|
113 |
+
$this->form["general"]->add(
|
114 |
+
$element->setLabel("CPU load priority")
|
115 |
+
->setDefault(isset($settings->cpuLoad) ? $settings->cpuLoad : "fast")
|
116 |
+
);
|
117 |
+
|
118 |
+
|
119 |
+
// Optimizer
|
120 |
+
$element = new Check(
|
121 |
+
"wpstg_settings[optimizer]",
|
122 |
+
array('1' => "Select the plugins you wish to disable during clone process")
|
123 |
+
);
|
124 |
+
|
125 |
+
$this->form["general"]->add(
|
126 |
+
$element->setLabel("Optimizer")
|
127 |
+
->setDefault((isset($settings->optimizer)) ? $settings->optimizer : null)
|
128 |
+
);
|
129 |
+
|
130 |
+
// Plugins
|
131 |
+
$plugins = array();
|
132 |
+
|
133 |
+
foreach (get_plugins() as $key => $data)
|
134 |
+
{
|
135 |
+
if ("wp-staging/wp-staging.php" === $key)
|
136 |
+
{
|
137 |
+
continue;
|
138 |
+
}
|
139 |
+
|
140 |
+
$plugins[$key] = $data["Name"];
|
141 |
+
}
|
142 |
+
|
143 |
+
$element = new Select(
|
144 |
+
"wpstg_settings[blackListedPlugins][]",
|
145 |
+
$plugins,
|
146 |
+
array(
|
147 |
+
"multiple" => "multiple",
|
148 |
+
"style" => "min-height:400px;"
|
149 |
+
)
|
150 |
+
);
|
151 |
+
|
152 |
+
$this->form["general"]->add(
|
153 |
+
$element->setDefault((isset($settings->blackListedPlugins)) ? $settings->blackListedPlugins : null)
|
154 |
+
);
|
155 |
+
|
156 |
+
// Disable admin authorization
|
157 |
+
$element = new Check(
|
158 |
+
"wpstg_settings[disableAdminLogin]",
|
159 |
+
array('1' => '')
|
160 |
+
);
|
161 |
+
|
162 |
+
$this->form["general"]->add(
|
163 |
+
$element->setLabel("Disable admin authorization")
|
164 |
+
->setDefault((isset($settings->disableAdminLogin)) ? $settings->disableAdminLogin : null)
|
165 |
+
);
|
166 |
+
|
167 |
+
// WordPress in subdirectory
|
168 |
+
$element = new Check(
|
169 |
+
"wpstg_settings[wpSubDirectory]",
|
170 |
+
array('1' => '')
|
171 |
+
);
|
172 |
+
|
173 |
+
$this->form["general"]->add(
|
174 |
+
$element->setLabel("Wordpress in subdirectory")
|
175 |
+
->setDefault((isset($settings->wpSubDirectory)) ? $settings->wpSubDirectory : null)
|
176 |
+
);
|
177 |
+
|
178 |
+
// Debug Mode
|
179 |
+
$element = new Check(
|
180 |
+
"wpstg_settings[debugMode]",
|
181 |
+
array('1' => '')
|
182 |
+
);
|
183 |
+
|
184 |
+
$this->form["general"]->add(
|
185 |
+
$element->setLabel("Debug Mode")
|
186 |
+
->setDefault((isset($settings->debugMode)) ? $settings->debugMode : null)
|
187 |
+
);
|
188 |
+
|
189 |
+
// Remove Data on Uninstall?
|
190 |
+
$element = new Check(
|
191 |
+
"wpstg_settings[unInstallOnDelete]",
|
192 |
+
array('1' => '')
|
193 |
+
);
|
194 |
+
|
195 |
+
$this->form["general"]->add(
|
196 |
+
$element->setLabel("Remove Data on Uninstall?")
|
197 |
+
->setDefault((isset($settings->unInstallOnDelete)) ? $settings->unInstallOnDelete : null)
|
198 |
+
);
|
199 |
+
|
200 |
+
// Check Directory Sizes
|
201 |
+
$element = new Check(
|
202 |
+
"wpstg_settings[checkDirectorySize]",
|
203 |
+
array('1' => '')
|
204 |
+
);
|
205 |
+
|
206 |
+
$this->form["general"]->add(
|
207 |
+
$element->setLabel("Check Directory Size")
|
208 |
+
->setDefault((isset($settings->checkDirectorySize)) ? $settings->checkDirectorySize : null)
|
209 |
+
);
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @param string $name
|
214 |
+
* @return array|Form
|
215 |
+
*/
|
216 |
+
public function get($name = null)
|
217 |
+
{
|
218 |
+
return (null === $name) ? $this->form : $this->form[$name];
|
219 |
+
}
|
220 |
}
|
apps/Backend/Notices/Notices.php
CHANGED
@@ -1,155 +1,155 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Notices;
|
4 |
-
|
5 |
-
/*
|
6 |
-
* Admin Notices | Warnings | Messages
|
7 |
-
*/
|
8 |
-
|
9 |
-
// No Direct Access
|
10 |
-
if( !defined( "WPINC" ) ) {
|
11 |
-
die;
|
12 |
-
}
|
13 |
-
|
14 |
-
use WPStaging\WPStaging;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Class Notices
|
18 |
-
* @package WPStaging\Backend\Notices
|
19 |
-
*/
|
20 |
-
class Notices {
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
private $path;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
private $url;
|
31 |
-
|
32 |
-
public function __construct( $path, $url ) {
|
33 |
-
$this->path = $path;
|
34 |
-
$this->url = $url;
|
35 |
-
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Check whether the page is an WP QUADS admin settings page or not
|
39 |
-
* @return bool
|
40 |
-
*/
|
41 |
-
private function isAdminPage() {
|
42 |
-
$currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
|
43 |
-
|
44 |
-
$availablePages = array(
|
45 |
-
"wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
|
46 |
-
);
|
47 |
-
|
48 |
-
//if( !is_admin() || !did_action( "wp_loaded" ) || !in_array( $currentPage, $availablePages, true ) ) {
|
49 |
-
if( !is_admin() || !in_array( $currentPage, $availablePages, true ) ) {
|
50 |
-
return false;
|
51 |
-
}
|
52 |
-
|
53 |
-
return true;
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Check if notice should be shown after certain days of installation
|
58 |
-
* @param int $days default 10
|
59 |
-
* @return bool
|
60 |
-
*/
|
61 |
-
private function canShow( $option, $days = 10 ) {
|
62 |
-
|
63 |
-
if( empty( $option ) ) {
|
64 |
-
return false;
|
65 |
-
}
|
66 |
-
|
67 |
-
$installDate = new \DateTime( get_option( "wpstg_installDate" ) );
|
68 |
-
$now = new \DateTime( "now" );
|
69 |
-
|
70 |
-
// Get days difference
|
71 |
-
$difference = $now->diff( $installDate )->days;
|
72 |
-
|
73 |
-
return ($days <= $difference && "no" !== get_option( $option ));
|
74 |
-
|
75 |
-
return false;
|
76 |
-
}
|
77 |
-
|
78 |
-
public function messages() {
|
79 |
-
|
80 |
-
$this->plugin_deactivated_notice();
|
81 |
-
|
82 |
-
// Do not display notices to user_roles lower than 'update_plugins'
|
83 |
-
if( !current_user_can( 'update_plugins' ) ) {
|
84 |
-
return;
|
85 |
-
}
|
86 |
-
|
87 |
-
$viewsNoticesPath = "{$this->path}views/_includes/messages/";
|
88 |
-
|
89 |
-
// Show rating review message on all admin pages
|
90 |
-
if( $this->canShow( "wpstg_rating", 7 ) ) {
|
91 |
-
require_once "{$viewsNoticesPath}rating.php";
|
92 |
-
}
|
93 |
-
|
94 |
-
|
95 |
-
// Display messages below on wp quads admin page only
|
96 |
-
if( !$this->isAdminPage() ) {
|
97 |
-
return;
|
98 |
-
}
|
99 |
-
|
100 |
-
|
101 |
-
$varsDirectory = \WPStaging\WPStaging::getContentDir();
|
102 |
-
|
103 |
-
|
104 |
-
// Poll do not show any longer
|
105 |
-
/* if( $this->canShow( "wpstg_poll", 7 ) ) {
|
106 |
-
require_once "{$viewsNoticesPath}poll.php";
|
107 |
-
} */
|
108 |
-
|
109 |
-
// Cache directory in uploads is not writable
|
110 |
-
if( !wp_is_writable( $varsDirectory ) ) {
|
111 |
-
require_once "{$viewsNoticesPath}/uploads-cache-directory-permission-problem.php";
|
112 |
-
}
|
113 |
-
// Staging directory is not writable
|
114 |
-
if( !wp_is_writable( get_home_path() ) ) {
|
115 |
-
require_once "{$viewsNoticesPath}/staging-directory-permission-problem.php";
|
116 |
-
}
|
117 |
-
|
118 |
-
// Version Control
|
119 |
-
if( version_compare( WPStaging::WP_COMPATIBLE, get_bloginfo( "version" ), "<" ) ) {
|
120 |
-
require_once "{$viewsNoticesPath}wp-version-compatible-message.php";
|
121 |
-
}
|
122 |
-
|
123 |
-
// Beta
|
124 |
-
if( false === get_option( "wpstg_beta" ) || "no" !== get_option( "wpstg_beta" ) ) {
|
125 |
-
require_once "{$viewsNoticesPath}beta.php";
|
126 |
-
}
|
127 |
-
|
128 |
-
// WP Staging Pro and Free can not be activated both
|
129 |
-
if( false !== ( $deactivatedNoticeID = get_transient( "wp_staging_deactivated_notice_id" ) ) ) {
|
130 |
-
require_once "{$viewsNoticesPath}transient.php";
|
131 |
-
delete_transient( "wp_staging_deactivated_notice_id" );
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Show a message when pro or free plugin becomes deactivated
|
137 |
-
*
|
138 |
-
* @return void
|
139 |
-
*/
|
140 |
-
private function plugin_deactivated_notice() {
|
141 |
-
if( false !== ( $deactivated_notice_id = get_transient( 'wp_staging_deactivated_notice_id' ) ) ) {
|
142 |
-
if( '1' === $deactivated_notice_id ) {
|
143 |
-
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging.", 'wpstg' );
|
144 |
-
} else {
|
145 |
-
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro.", 'wpstg' );
|
146 |
-
}
|
147 |
-
?>
|
148 |
-
<div class="updated notice is-dismissible" style="border-left: 4px solid #ffba00;">
|
149 |
-
<p><?php echo esc_html( $message ); ?></p>
|
150 |
-
</div> <?php
|
151 |
-
delete_transient( 'wp_staging_deactivated_notice_id' );
|
152 |
-
}
|
153 |
-
}
|
154 |
-
|
155 |
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Notices;
|
4 |
+
|
5 |
+
/*
|
6 |
+
* Admin Notices | Warnings | Messages
|
7 |
+
*/
|
8 |
+
|
9 |
+
// No Direct Access
|
10 |
+
if( !defined( "WPINC" ) ) {
|
11 |
+
die;
|
12 |
+
}
|
13 |
+
|
14 |
+
use WPStaging\WPStaging;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class Notices
|
18 |
+
* @package WPStaging\Backend\Notices
|
19 |
+
*/
|
20 |
+
class Notices {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $path;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
private $url;
|
31 |
+
|
32 |
+
public function __construct( $path, $url ) {
|
33 |
+
$this->path = $path;
|
34 |
+
$this->url = $url;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Check whether the page is an WP QUADS admin settings page or not
|
39 |
+
* @return bool
|
40 |
+
*/
|
41 |
+
private function isAdminPage() {
|
42 |
+
$currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
|
43 |
+
|
44 |
+
$availablePages = array(
|
45 |
+
"wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
|
46 |
+
);
|
47 |
+
|
48 |
+
//if( !is_admin() || !did_action( "wp_loaded" ) || !in_array( $currentPage, $availablePages, true ) ) {
|
49 |
+
if( !is_admin() || !in_array( $currentPage, $availablePages, true ) ) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
return true;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Check if notice should be shown after certain days of installation
|
58 |
+
* @param int $days default 10
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
private function canShow( $option, $days = 10 ) {
|
62 |
+
|
63 |
+
if( empty( $option ) ) {
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
|
67 |
+
$installDate = new \DateTime( get_option( "wpstg_installDate" ) );
|
68 |
+
$now = new \DateTime( "now" );
|
69 |
+
|
70 |
+
// Get days difference
|
71 |
+
$difference = $now->diff( $installDate )->days;
|
72 |
+
|
73 |
+
return ($days <= $difference && "no" !== get_option( $option ));
|
74 |
+
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
|
78 |
+
public function messages() {
|
79 |
+
|
80 |
+
$this->plugin_deactivated_notice();
|
81 |
+
|
82 |
+
// Do not display notices to user_roles lower than 'update_plugins'
|
83 |
+
if( !current_user_can( 'update_plugins' ) ) {
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
|
87 |
+
$viewsNoticesPath = "{$this->path}views/_includes/messages/";
|
88 |
+
|
89 |
+
// Show rating review message on all admin pages
|
90 |
+
if( $this->canShow( "wpstg_rating", 7 ) ) {
|
91 |
+
require_once "{$viewsNoticesPath}rating.php";
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
// Display messages below on wp quads admin page only
|
96 |
+
if( !$this->isAdminPage() ) {
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
$varsDirectory = \WPStaging\WPStaging::getContentDir();
|
102 |
+
|
103 |
+
|
104 |
+
// Poll do not show any longer
|
105 |
+
/* if( $this->canShow( "wpstg_poll", 7 ) ) {
|
106 |
+
require_once "{$viewsNoticesPath}poll.php";
|
107 |
+
} */
|
108 |
+
|
109 |
+
// Cache directory in uploads is not writable
|
110 |
+
if( !wp_is_writable( $varsDirectory ) ) {
|
111 |
+
require_once "{$viewsNoticesPath}/uploads-cache-directory-permission-problem.php";
|
112 |
+
}
|
113 |
+
// Staging directory is not writable
|
114 |
+
if( !wp_is_writable( get_home_path() ) ) {
|
115 |
+
require_once "{$viewsNoticesPath}/staging-directory-permission-problem.php";
|
116 |
+
}
|
117 |
+
|
118 |
+
// Version Control
|
119 |
+
if( version_compare( WPStaging::WP_COMPATIBLE, get_bloginfo( "version" ), "<" ) ) {
|
120 |
+
require_once "{$viewsNoticesPath}wp-version-compatible-message.php";
|
121 |
+
}
|
122 |
+
|
123 |
+
// Beta
|
124 |
+
if( false === get_option( "wpstg_beta" ) || "no" !== get_option( "wpstg_beta" ) ) {
|
125 |
+
require_once "{$viewsNoticesPath}beta.php";
|
126 |
+
}
|
127 |
+
|
128 |
+
// WP Staging Pro and Free can not be activated both
|
129 |
+
if( false !== ( $deactivatedNoticeID = get_transient( "wp_staging_deactivated_notice_id" ) ) ) {
|
130 |
+
require_once "{$viewsNoticesPath}transient.php";
|
131 |
+
delete_transient( "wp_staging_deactivated_notice_id" );
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Show a message when pro or free plugin becomes deactivated
|
137 |
+
*
|
138 |
+
* @return void
|
139 |
+
*/
|
140 |
+
private function plugin_deactivated_notice() {
|
141 |
+
if( false !== ( $deactivated_notice_id = get_transient( 'wp_staging_deactivated_notice_id' ) ) ) {
|
142 |
+
if( '1' === $deactivated_notice_id ) {
|
143 |
+
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging.", 'wpstg' );
|
144 |
+
} else {
|
145 |
+
$message = __( "WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro.", 'wpstg' );
|
146 |
+
}
|
147 |
+
?>
|
148 |
+
<div class="updated notice is-dismissible" style="border-left: 4px solid #ffba00;">
|
149 |
+
<p><?php echo esc_html( $message ); ?></p>
|
150 |
+
</div> <?php
|
151 |
+
delete_transient( 'wp_staging_deactivated_notice_id' );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
}
|
apps/Backend/Upgrade/Upgrade.php
CHANGED
@@ -1,229 +1,221 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend\Upgrade;
|
4 |
-
|
5 |
-
use WPStaging\WPStaging;
|
6 |
-
use WPStaging\Utils\Logger;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Upgrade Class
|
10 |
-
* This must be loaded on every page init to ensure all settings are
|
11 |
-
* adjusted correctly and to run any upgrade process if necessary.
|
12 |
-
*/
|
13 |
-
|
14 |
-
// No Direct Access
|
15 |
-
if( !defined( "WPINC" ) ) {
|
16 |
-
die;
|
17 |
-
}
|
18 |
-
|
19 |
-
class Upgrade {
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Previous Version number
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
private $previousVersion;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* Clone data
|
29 |
-
* @var obj
|
30 |
-
*/
|
31 |
-
private $clones;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Clone data
|
35 |
-
* @var obj
|
36 |
-
*/
|
37 |
-
private $clonesBeta;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Cron data
|
41 |
-
* @var obj
|
42 |
-
*/
|
43 |
-
private $cron;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Logger
|
47 |
-
* @var obj
|
48 |
-
*/
|
49 |
-
private $logger;
|
50 |
-
|
51 |
-
public function __construct() {
|
52 |
-
|
53 |
-
// add wpstg_weekly_event to cron events
|
54 |
-
$this->cron = new \WPStaging\Cron\Cron;
|
55 |
-
|
56 |
-
// Previous version
|
57 |
-
$this->previousVersion = preg_replace( '/[^0-9.].*/', '', get_option( 'wpstg_version' ) );
|
58 |
-
|
59 |
-
// Options earlier than version 2.0.0
|
60 |
-
$this->clones = get_option( "wpstg_existing_clones", array() );
|
61 |
-
|
62 |
-
// Current options
|
63 |
-
$this->clonesBeta = get_option( "wpstg_existing_clones_beta", array() );
|
64 |
-
|
65 |
-
// Logger
|
66 |
-
$this->logger = new Logger;
|
67 |
-
}
|
68 |
-
|
69 |
-
public function doUpgrade() {
|
70 |
-
$this->upgrade2_0_3();
|
71 |
-
//$this->upgrade2_0_4();
|
72 |
-
$this->upgrade2_1_2();
|
73 |
-
$this->setVersion();
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Upgrade method 2.0.3
|
78 |
-
*/
|
79 |
-
public function upgrade2_0_3() {
|
80 |
-
// Previous version lower than 2.0.2 or new install
|
81 |
-
if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.0.2', '<' ) ) {
|
82 |
-
$this->upgradeOptions();
|
83 |
-
$this->upgradeClonesBeta();
|
84 |
-
$this->upgradeNotices();
|
85 |
-
}
|
86 |
-
}
|
87 |
-
|
88 |
-
|
89 |
-
* Upgrade method 2.
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
*
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
$
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
$
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
$rating
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
update_option( 'wpstg_beta', 'no' );
|
223 |
-
}
|
224 |
-
if( $rating && $rating === 'yes' ) {
|
225 |
-
update_option( 'wpstg_rating', 'no' );
|
226 |
-
}
|
227 |
-
}
|
228 |
-
|
229 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend\Upgrade;
|
4 |
+
|
5 |
+
use WPStaging\WPStaging;
|
6 |
+
use WPStaging\Utils\Logger;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Upgrade Class
|
10 |
+
* This must be loaded on every page init to ensure all settings are
|
11 |
+
* adjusted correctly and to run any upgrade process if necessary.
|
12 |
+
*/
|
13 |
+
|
14 |
+
// No Direct Access
|
15 |
+
if( !defined( "WPINC" ) ) {
|
16 |
+
die;
|
17 |
+
}
|
18 |
+
|
19 |
+
class Upgrade {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Previous Version number
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $previousVersion;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Clone data
|
29 |
+
* @var obj
|
30 |
+
*/
|
31 |
+
private $clones;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Clone data
|
35 |
+
* @var obj
|
36 |
+
*/
|
37 |
+
private $clonesBeta;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Cron data
|
41 |
+
* @var obj
|
42 |
+
*/
|
43 |
+
private $cron;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Logger
|
47 |
+
* @var obj
|
48 |
+
*/
|
49 |
+
private $logger;
|
50 |
+
|
51 |
+
public function __construct() {
|
52 |
+
|
53 |
+
// add wpstg_weekly_event to cron events
|
54 |
+
$this->cron = new \WPStaging\Cron\Cron;
|
55 |
+
|
56 |
+
// Previous version
|
57 |
+
$this->previousVersion = preg_replace( '/[^0-9.].*/', '', get_option( 'wpstg_version' ) );
|
58 |
+
|
59 |
+
// Options earlier than version 2.0.0
|
60 |
+
$this->clones = get_option( "wpstg_existing_clones", array() );
|
61 |
+
|
62 |
+
// Current options
|
63 |
+
$this->clonesBeta = get_option( "wpstg_existing_clones_beta", array() );
|
64 |
+
|
65 |
+
// Logger
|
66 |
+
$this->logger = new Logger;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function doUpgrade() {
|
70 |
+
$this->upgrade2_0_3();
|
71 |
+
//$this->upgrade2_0_4();
|
72 |
+
$this->upgrade2_1_2();
|
73 |
+
$this->setVersion();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Upgrade method 2.0.3
|
78 |
+
*/
|
79 |
+
public function upgrade2_0_3() {
|
80 |
+
// Previous version lower than 2.0.2 or new install
|
81 |
+
if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.0.2', '<' ) ) {
|
82 |
+
$this->upgradeOptions();
|
83 |
+
$this->upgradeClonesBeta();
|
84 |
+
$this->upgradeNotices();
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Upgrade method 2.1.2
|
90 |
+
* Sanitize the clone key value.
|
91 |
+
*/
|
92 |
+
private function upgrade2_1_2() {
|
93 |
+
|
94 |
+
// Current options
|
95 |
+
$this->clonesBeta = get_option( "wpstg_existing_clones_beta", array() );
|
96 |
+
|
97 |
+
if( false === $this->previousVersion || version_compare( $this->previousVersion, '2.1.7', '<' ) ) {
|
98 |
+
foreach ( $this->clonesBeta as $key => $value ) {
|
99 |
+
unset( $this->clonesBeta[$key] );
|
100 |
+
$this->clonesBeta[preg_replace( "#\W+#", '-', strtolower( $key ) )] = $value;
|
101 |
+
}
|
102 |
+
if( empty( $this->clonesBeta ) )
|
103 |
+
return false;
|
104 |
+
|
105 |
+
update_option( 'wpstg_existing_clones_beta', $this->clonesBeta );
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Upgrade routine for new install
|
111 |
+
*/
|
112 |
+
private function upgradeOptions() {
|
113 |
+
// Write some default vars
|
114 |
+
add_option( 'wpstg_installDate', date( 'Y-m-d h:i:s' ) );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Write new version number into db
|
119 |
+
* return bool
|
120 |
+
*/
|
121 |
+
private function setVersion() {
|
122 |
+
// Check if version number in DB is lower than version number in current plugin
|
123 |
+
if( version_compare( $this->previousVersion, \WPStaging\WPStaging::VERSION, '<' ) ) {
|
124 |
+
// Update Version number
|
125 |
+
update_option( 'wpstg_version', preg_replace( '/[^0-9.].*/', '', \WPStaging\WPStaging::VERSION ) );
|
126 |
+
// Update "upgraded from" version number
|
127 |
+
update_option( 'wpstg_version_upgraded_from', preg_replace( '/[^0-9.].*/', '', $this->previousVersion ) );
|
128 |
+
|
129 |
+
return true;
|
130 |
+
}
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Create a new db option for beta version 2.0.2
|
136 |
+
* @return bool
|
137 |
+
*/
|
138 |
+
private function upgradeClonesBeta() {
|
139 |
+
|
140 |
+
// Copy old data to new option
|
141 |
+
//update_option( 'wpstg_existing_clones_beta', $this->clones );
|
142 |
+
|
143 |
+
$new = array();
|
144 |
+
|
145 |
+
if( empty( $this->clones ) ) {
|
146 |
+
return false;
|
147 |
+
}
|
148 |
+
|
149 |
+
|
150 |
+
foreach ( $this->clones as $key => &$value ) {
|
151 |
+
|
152 |
+
// Skip the rest of the loop if data is already compatible to wpstg 2.0.2
|
153 |
+
if( isset( $value['directoryName'] ) || !empty( $value['directoryName'] ) ) {
|
154 |
+
continue;
|
155 |
+
}
|
156 |
+
|
157 |
+
$new[$value]['directoryName'] = $value;
|
158 |
+
$new[$value]['path'] = get_home_path() . $value;
|
159 |
+
$new[$value]['url'] = get_home_url() . "/" . $value;
|
160 |
+
$new[$value]['number'] = $key + 1;
|
161 |
+
$new[$value]['version'] = $this->previousVersion;
|
162 |
+
}
|
163 |
+
unset( $value );
|
164 |
+
|
165 |
+
if( empty( $new ) || false === update_option( 'wpstg_existing_clones_beta', $new ) ) {
|
166 |
+
$this->logger->log( 'Failed to upgrade clone data from ' . $this->previousVersion . ' to ' . \WPStaging\WPStaging::VERSION );
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Convert clone data from wpstg 1.x to wpstg 2.x
|
172 |
+
* Only use this later when wpstg 2.x is ready for production
|
173 |
+
*/
|
174 |
+
private function upgradeClones() {
|
175 |
+
|
176 |
+
$new = array();
|
177 |
+
|
178 |
+
if( empty( $this->clones ) ) {
|
179 |
+
return false;
|
180 |
+
}
|
181 |
+
|
182 |
+
foreach ( $this->clones as $key => &$value ) {
|
183 |
+
|
184 |
+
// Skip the rest of the loop if data is already compatible to wpstg 2.0.1
|
185 |
+
if( isset( $value['directoryName'] ) || !empty( $value['directoryName'] ) ) {
|
186 |
+
continue;
|
187 |
+
}
|
188 |
+
$new[$value]['directoryName'] = $value;
|
189 |
+
$new[$value]['path'] = get_home_path() . $value;
|
190 |
+
$new[$value]['url'] = get_home_url() . "/" . $value;
|
191 |
+
$new[$value]['number'] = $key + 1;
|
192 |
+
$new[$value]['version'] = $this->previousVersion;
|
193 |
+
}
|
194 |
+
unset( $value );
|
195 |
+
|
196 |
+
if( empty( $new ) || false === update_option( 'wpstg_existing_clones', $new ) ) {
|
197 |
+
$this->logger->log( 'Failed to upgrade clone data from ' . $this->previousVersion . ' to ' . \WPStaging\WPStaging::VERSION );
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Upgrade Notices db options from wpstg 1.3 -> 2.0.1
|
203 |
+
* Fix some logical db options
|
204 |
+
*/
|
205 |
+
private function upgradeNotices() {
|
206 |
+
$poll = get_option( "wpstg_start_poll", false );
|
207 |
+
$beta = get_option( "wpstg_hide_beta", false );
|
208 |
+
$rating = get_option( "wpstg_RatingDiv", false );
|
209 |
+
|
210 |
+
if( $poll && $poll === "no" ) {
|
211 |
+
update_option( 'wpstg_poll', 'no' );
|
212 |
+
}
|
213 |
+
if( $beta && $beta === "yes" ) {
|
214 |
+
update_option( 'wpstg_beta', 'no' );
|
215 |
+
}
|
216 |
+
if( $rating && $rating === 'yes' ) {
|
217 |
+
update_option( 'wpstg_rating', 'no' );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apps/Backend/public/css/wpstg-admin.css
CHANGED
@@ -1,784 +1,784 @@
|
|
1 |
-
/**
|
2 |
-
* WPSTG Admin CSS
|
3 |
-
*
|
4 |
-
* @package WPSTG
|
5 |
-
* @subpackage Admin CSS
|
6 |
-
* @copyright Copyright (c) 2015, René Hermenau
|
7 |
-
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
8 |
-
*/
|
9 |
-
|
10 |
-
|
11 |
-
/* CSS for Tabs */
|
12 |
-
|
13 |
-
#tab_container ul {
|
14 |
-
/*height: 200px;*/
|
15 |
-
list-style: none;
|
16 |
-
margin: 0;
|
17 |
-
padding: 0;
|
18 |
-
background: #f1f1f1;
|
19 |
-
float: left;
|
20 |
-
/*list-style-type: square;*/
|
21 |
-
}
|
22 |
-
|
23 |
-
#tab_container ul li:first-child.selected-tab {
|
24 |
-
border-top: none;
|
25 |
-
}
|
26 |
-
|
27 |
-
#tab_container ul li a.selected-tab {
|
28 |
-
font-weight: bold;
|
29 |
-
text-decoration: none;
|
30 |
-
}
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
#tab_container .row{
|
35 |
-
padding-top:10px;
|
36 |
-
padding-bottom:12px;
|
37 |
-
}
|
38 |
-
|
39 |
-
#wpstg-tools .nav-tab-wrapper{
|
40 |
-
padding:0;
|
41 |
-
}
|
42 |
-
|
43 |
-
|
44 |
-
#tab_container .row label strong, #tab_container .row strong {
|
45 |
-
font-weight: bold;
|
46 |
-
}
|
47 |
-
|
48 |
-
.wpstg-tabs a {
|
49 |
-
padding:5px;
|
50 |
-
}
|
51 |
-
|
52 |
-
#tab_container > ul > li.wpstg-tabs.active {
|
53 |
-
background-color:white;
|
54 |
-
}
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
#wpstg_settingsgeneral_header .row:nth-child(3), #wpstg_settingsgeneral_header .row:nth-child(4){
|
59 |
-
display:none;
|
60 |
-
}
|
61 |
-
|
62 |
-
/* Layout of admin table and rows
|
63 |
-
*/
|
64 |
-
|
65 |
-
#tab_container .panel-container {
|
66 |
-
background: #FFF;
|
67 |
-
padding:0 20px 20px 20px;
|
68 |
-
overflow:auto;
|
69 |
-
}
|
70 |
-
|
71 |
-
#tab_container .form-table th {
|
72 |
-
vertical-align: top;
|
73 |
-
text-align: left;
|
74 |
-
padding: 20px 10px 20px 0;
|
75 |
-
line-height: 1.3;
|
76 |
-
font-weight: bold;
|
77 |
-
font-size: 14px;
|
78 |
-
color:#484848;
|
79 |
-
width: 30%;
|
80 |
-
}
|
81 |
-
|
82 |
-
#tab_container .form-table tr {
|
83 |
-
border-bottom: 1px solid #E7E7E7;
|
84 |
-
}
|
85 |
-
|
86 |
-
#tab_container span.description{
|
87 |
-
display: block;
|
88 |
-
font-weight: 400;
|
89 |
-
font-style: normal;
|
90 |
-
font-size: 13px;
|
91 |
-
margin-top: 7px;
|
92 |
-
color:#484848;
|
93 |
-
}
|
94 |
-
|
95 |
-
#tab_container .col-title{
|
96 |
-
color:#484848;
|
97 |
-
}
|
98 |
-
|
99 |
-
@media only screen and (max-width:680px) {
|
100 |
-
#tab_container ul {
|
101 |
-
float:none;
|
102 |
-
}
|
103 |
-
#tab_container .form-table tr > th {
|
104 |
-
width:100%;
|
105 |
-
}
|
106 |
-
#tab_container span.description{
|
107 |
-
font-size: 14px;
|
108 |
-
}
|
109 |
-
#tab_container .form-table tr > th, #tab_container .form-table tr > td {
|
110 |
-
padding:10px;
|
111 |
-
}
|
112 |
-
}
|
113 |
-
|
114 |
-
#tab_container ul li {
|
115 |
-
margin-bottom:0;
|
116 |
-
}
|
117 |
-
|
118 |
-
#tab_container ul li a {
|
119 |
-
display: block;
|
120 |
-
padding:10px 4px 10px 14px;
|
121 |
-
border-width: 1px 0;
|
122 |
-
border-style: solid;
|
123 |
-
border-top-color:white;
|
124 |
-
border-bottom-color:#e7e7e7;
|
125 |
-
text-decoration: none;
|
126 |
-
color: #0097DF;
|
127 |
-
font-weight: bold;
|
128 |
-
}
|
129 |
-
#tab_container ul li a:hover {
|
130 |
-
background-color: #e5e5e5;
|
131 |
-
color:#777777;
|
132 |
-
}
|
133 |
-
|
134 |
-
|
135 |
-
.wp-staginglogo{
|
136 |
-
display: block;
|
137 |
-
font-size:16px;
|
138 |
-
padding-top:20px;
|
139 |
-
width:220px;
|
140 |
-
float:left;
|
141 |
-
}
|
142 |
-
|
143 |
-
.wpstg-version{
|
144 |
-
display: block;
|
145 |
-
padding-top:29px
|
146 |
-
}
|
147 |
-
|
148 |
-
|
149 |
-
.wpstg_admin .nav-tab {
|
150 |
-
color: #3C3C3C;
|
151 |
-
}
|
152 |
-
|
153 |
-
|
154 |
-
#tab_container table tbody tr:nth-child(1) > th > div {
|
155 |
-
font-size: 20px;
|
156 |
-
}
|
157 |
-
|
158 |
-
.wpstg_hidden{
|
159 |
-
display: none;
|
160 |
-
}
|
161 |
-
|
162 |
-
/* End layout of admin table and rows
|
163 |
-
*/
|
164 |
-
#mashtabcontainer > .mashtabs {
|
165 |
-
background-color: #ffffff;
|
166 |
-
}
|
167 |
-
|
168 |
-
#mashtabcontainer ul .active {
|
169 |
-
background-color: #00adef;
|
170 |
-
color: white;
|
171 |
-
border-bottom-color: #0098D2;
|
172 |
-
}
|
173 |
-
|
174 |
-
#mashtabcontainer ul .active:hover {
|
175 |
-
background-color: #00A4E2;
|
176 |
-
color: white;
|
177 |
-
border-bottom-color: #0098D2;
|
178 |
-
}
|
179 |
-
|
180 |
-
#mashtabcontainer ul li a {
|
181 |
-
padding: 10px 14px 10px 14px;
|
182 |
-
background-color: #f3f3f3
|
183 |
-
|
184 |
-
}
|
185 |
-
|
186 |
-
#mashtabcontainer .mashtab-container {
|
187 |
-
border: 0 solid #ececec;
|
188 |
-
}
|
189 |
-
|
190 |
-
/* Cloning workflow */
|
191 |
-
#wpstg-clonepage-wrapper {
|
192 |
-
margin-bottom: 20px;
|
193 |
-
/*width: 690px; */
|
194 |
-
}
|
195 |
-
|
196 |
-
@media screen and (min-width:1090px){
|
197 |
-
#wpstg-clonepage-wrapper {
|
198 |
-
float: left;
|
199 |
-
margin-bottom: 20px;
|
200 |
-
/*width: 690px;*/
|
201 |
-
}
|
202 |
-
.wpstg-sidebar{
|
203 |
-
display: none;
|
204 |
-
margin-left: 700px;
|
205 |
-
margin-top: 138px;
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
.wpstg-sidebar{
|
210 |
-
display: none;
|
211 |
-
padding: 10px;
|
212 |
-
border: 1px solid #DFDFDF;
|
213 |
-
max-width: 250px;
|
214 |
-
height: 250px;
|
215 |
-
}
|
216 |
-
|
217 |
-
#wpstg-steps {
|
218 |
-
margin-top:30px;
|
219 |
-
}
|
220 |
-
|
221 |
-
#wpstg-steps li {
|
222 |
-
color: #444;
|
223 |
-
line-height: 20px;
|
224 |
-
padding-right:10px;
|
225 |
-
float:left;
|
226 |
-
}
|
227 |
-
|
228 |
-
|
229 |
-
.wpstg-step-num {
|
230 |
-
border: 1px solid #444;
|
231 |
-
border-radius: 3px;
|
232 |
-
display: inline-block;
|
233 |
-
width: 20px;
|
234 |
-
height: 20px;
|
235 |
-
text-align: center;
|
236 |
-
margin-right: 5px;
|
237 |
-
}
|
238 |
-
|
239 |
-
.wpstg-current-step {
|
240 |
-
font-weight: bold;
|
241 |
-
}
|
242 |
-
|
243 |
-
.wpstg-current-step .wpstg-step-num {
|
244 |
-
background: #444;
|
245 |
-
color: #eee;
|
246 |
-
}
|
247 |
-
|
248 |
-
.wpstg-clone {
|
249 |
-
border: 3px solid #ffffff;
|
250 |
-
margin-bottom: 5px;
|
251 |
-
padding: 5px 10px;
|
252 |
-
width: 300px;
|
253 |
-
position: relative;
|
254 |
-
overflow: hidden;
|
255 |
-
transition: border-color .2s ease-in-out;
|
256 |
-
background-color: #DDDDDD;
|
257 |
-
}
|
258 |
-
|
259 |
-
.wpstg-clone.active {
|
260 |
-
border-color: #1d94cf;;
|
261 |
-
}
|
262 |
-
|
263 |
-
.wpstg-clone-title {
|
264 |
-
display: inline-block;
|
265 |
-
font-size: 15px;
|
266 |
-
max-width: 130px;
|
267 |
-
text-decoration: none;
|
268 |
-
font-weight: bold;
|
269 |
-
color:#0285AE;
|
270 |
-
}
|
271 |
-
|
272 |
-
.wpstg-clone-action {
|
273 |
-
background: #ffffff;
|
274 |
-
border-left: 1px solid #ccc;
|
275 |
-
color: #bbb;
|
276 |
-
padding: 0 5px;
|
277 |
-
float: right;
|
278 |
-
text-decoration: none;
|
279 |
-
position: relative;
|
280 |
-
transition: color .2s ease-in-out;
|
281 |
-
}
|
282 |
-
|
283 |
-
.wpstg-remove-clone:hover {
|
284 |
-
color: #ef6d6d;
|
285 |
-
}
|
286 |
-
|
287 |
-
.wpstg-clone-action:last-child {
|
288 |
-
border: none;
|
289 |
-
}
|
290 |
-
|
291 |
-
.wpstg-clone:hover .wpstg-clone-action {
|
292 |
-
display: inline-block;
|
293 |
-
}
|
294 |
-
|
295 |
-
#wpstg-show-error-details:focus,
|
296 |
-
#wpstg-workflow .wpstg-clone-action {
|
297 |
-
outline: none;
|
298 |
-
box-shadow: none;
|
299 |
-
}
|
300 |
-
|
301 |
-
.wpstg-link-btn {
|
302 |
-
background: #45a1c9;
|
303 |
-
color: #fff;
|
304 |
-
display: inline-block;
|
305 |
-
padding: 5px 10px;
|
306 |
-
text-decoration: none;
|
307 |
-
vertical-align: baseline;
|
308 |
-
transition: all .2s ease-in-out;
|
309 |
-
}
|
310 |
-
|
311 |
-
.wpstg-link-btn:hover,
|
312 |
-
.wpstg-link-btn:focus {
|
313 |
-
color: #fff;
|
314 |
-
outline: none;
|
315 |
-
box-shadow: none;
|
316 |
-
}
|
317 |
-
|
318 |
-
#wpstg-workflow .wpstg-link-btn:active {
|
319 |
-
vertical-align: baseline;
|
320 |
-
}
|
321 |
-
|
322 |
-
.wpstg-link-btn[disabled] {
|
323 |
-
background: #777 !important;
|
324 |
-
pointer-events: none;
|
325 |
-
}
|
326 |
-
|
327 |
-
#wpstg-cancel-cloning {
|
328 |
-
background: #ff3428;
|
329 |
-
border-color: #e72f24;
|
330 |
-
margin-top: 5px;
|
331 |
-
}
|
332 |
-
|
333 |
-
#wpstg-cancel-cloning.success {
|
334 |
-
background: #64dd58;
|
335 |
-
border-color: #54bd4a;
|
336 |
-
}
|
337 |
-
|
338 |
-
#wpstg-error-wrapper,
|
339 |
-
#wpstg-error-details {
|
340 |
-
display:none;
|
341 |
-
padding-top: 10px;
|
342 |
-
font-size: 13px;
|
343 |
-
clear:both;
|
344 |
-
}
|
345 |
-
|
346 |
-
#wpstg-show-error-details {
|
347 |
-
display: inline-block;
|
348 |
-
margin-left: 5px;
|
349 |
-
color: #555;
|
350 |
-
text-decoration: none;
|
351 |
-
transition: color .2s ease-in-out;
|
352 |
-
}
|
353 |
-
|
354 |
-
#wpstg-show-error-details:hover {
|
355 |
-
color: #1d94cf;
|
356 |
-
}
|
357 |
-
|
358 |
-
#wpstg-error-details {
|
359 |
-
border-left: 5px solid #ef6d6d;
|
360 |
-
padding: 10px;
|
361 |
-
width: 500px;
|
362 |
-
}
|
363 |
-
|
364 |
-
#wpstg-home-link,
|
365 |
-
#wpstg-try-again {
|
366 |
-
display: none;
|
367 |
-
}
|
368 |
-
|
369 |
-
|
370 |
-
#wpstg-loader {
|
371 |
-
content: url('../img/loading.gif');
|
372 |
-
margin-top:-5px;
|
373 |
-
}
|
374 |
-
|
375 |
-
#wpstg-loader.wpstg-finished {
|
376 |
-
content:"Finished";
|
377 |
-
background-color:#00c89a;
|
378 |
-
color:white;
|
379 |
-
padding:2px;
|
380 |
-
margin-top:6px;
|
381 |
-
}
|
382 |
-
|
383 |
-
#wpstg-workflow {
|
384 |
-
position: relative;
|
385 |
-
clear:both;
|
386 |
-
padding-top:20px;
|
387 |
-
margin-right:20px;
|
388 |
-
float:left;
|
389 |
-
min-width: 500px;
|
390 |
-
border-right: 1px solid #DFDFDF;
|
391 |
-
min-height: 380px;
|
392 |
-
padding-right: 20px;
|
393 |
-
}
|
394 |
-
|
395 |
-
#wpstg-sidebar {
|
396 |
-
float: left;
|
397 |
-
max-width: 400px;
|
398 |
-
display: block;
|
399 |
-
}
|
400 |
-
|
401 |
-
@media screen and (max-width:1150px){
|
402 |
-
#wpstg-sidebar img{
|
403 |
-
margin-top: 30px;
|
404 |
-
}
|
405 |
-
}
|
406 |
-
|
407 |
-
#wpstg-workflow.loading::after,
|
408 |
-
#wpstg-removing-clone.loading::after {
|
409 |
-
background: rgba(255, 255, 255, .7);
|
410 |
-
content: 'Loading... may take a while for huge websites';
|
411 |
-
display: block;
|
412 |
-
width: 100%;
|
413 |
-
height: 100%;
|
414 |
-
font-size: 20px;
|
415 |
-
padding-top: 100px;
|
416 |
-
text-align: center;
|
417 |
-
position: absolute;
|
418 |
-
top: 0;
|
419 |
-
left: 0;
|
420 |
-
z-index: 99;
|
421 |
-
}
|
422 |
-
|
423 |
-
#wpstg-removing-clone.loading::after {
|
424 |
-
content: 'REMOVING' !important;
|
425 |
-
}
|
426 |
-
|
427 |
-
#wpstg-existing-clones,
|
428 |
-
#wpstg-removing-clone {
|
429 |
-
position: relative;
|
430 |
-
}
|
431 |
-
|
432 |
-
.wpstg-progress-bar {
|
433 |
-
max-width: 900px;
|
434 |
-
height: 27px;
|
435 |
-
padding: 0;
|
436 |
-
background-color: #d6d8d7;
|
437 |
-
}
|
438 |
-
|
439 |
-
.wpstg-progress {
|
440 |
-
background: #1d94cf;
|
441 |
-
width: 0;
|
442 |
-
height: 100%;
|
443 |
-
transition: width 1s;
|
444 |
-
color:white;
|
445 |
-
line-height:25px;
|
446 |
-
text-align:center;
|
447 |
-
}
|
448 |
-
|
449 |
-
#wpstg-new-clone-id.wpstg-error-input,
|
450 |
-
#wpstg-clone-path.wpstg-error-input {
|
451 |
-
border: 1px solid #ff4235;
|
452 |
-
box-shadow: 0 0 2px rgba(255, 66, 53, .8);
|
453 |
-
}
|
454 |
-
|
455 |
-
#wpstg-clone-path {
|
456 |
-
margin-left: 10px;
|
457 |
-
width: 350px;
|
458 |
-
}
|
459 |
-
|
460 |
-
.wpstg-error-msg {
|
461 |
-
color: #ff4235;
|
462 |
-
}
|
463 |
-
|
464 |
-
#wpstg-clone-id-error {
|
465 |
-
display: block;
|
466 |
-
text-align: right;
|
467 |
-
margin-right: 90px;
|
468 |
-
}
|
469 |
-
|
470 |
-
#wpstg-start-cloning + .wpstg-error-msg {
|
471 |
-
display: block;
|
472 |
-
margin-top: 5px;
|
473 |
-
}
|
474 |
-
|
475 |
-
.wpstg-size-info {
|
476 |
-
color: #999;
|
477 |
-
font-weight: normal;
|
478 |
-
position: relative;
|
479 |
-
left: 2px;
|
480 |
-
}
|
481 |
-
|
482 |
-
.wpstg-db-table .wpstg-size-info {
|
483 |
-
top: 2px;
|
484 |
-
}
|
485 |
-
|
486 |
-
#wpstg-workflow #wpstg-start-cloning {
|
487 |
-
display: inline-block;
|
488 |
-
margin-left: 5px;
|
489 |
-
font-size: 14px;
|
490 |
-
vertical-align: baseline;
|
491 |
-
}
|
492 |
-
|
493 |
-
/* Tabs */
|
494 |
-
.wpstg-tabs-wrapper {
|
495 |
-
max-width: 640px;
|
496 |
-
margin: 10px 0;
|
497 |
-
}
|
498 |
-
|
499 |
-
#wpstg-path-wrapper {
|
500 |
-
border-bottom: 2px dashed #ccc;
|
501 |
-
padding-bottom: 10px;
|
502 |
-
margin-bottom: 10px;
|
503 |
-
}
|
504 |
-
|
505 |
-
.wpstg-tabs-wrapper {
|
506 |
-
border: 1px solid #ddd;
|
507 |
-
border-right: none;
|
508 |
-
border-left: none;
|
509 |
-
}
|
510 |
-
|
511 |
-
.wpstg-tab-section {
|
512 |
-
border: 1px solid #ddd;
|
513 |
-
border-right: none;
|
514 |
-
border-left: none;
|
515 |
-
display: none;
|
516 |
-
padding: 20px;
|
517 |
-
}
|
518 |
-
|
519 |
-
.wpstg-tab-section::after {
|
520 |
-
display: block;
|
521 |
-
content: '';
|
522 |
-
clear: both;
|
523 |
-
}
|
524 |
-
|
525 |
-
.wpstg-tab-header {
|
526 |
-
border: 1px solid #ddd;
|
527 |
-
border-right: none;
|
528 |
-
border-left: none;
|
529 |
-
color: #444;
|
530 |
-
font-size: 16px;
|
531 |
-
font-weight: bolder;
|
532 |
-
display: block;
|
533 |
-
padding: 10px;;
|
534 |
-
text-decoration: none;
|
535 |
-
}
|
536 |
-
|
537 |
-
.wpstg-tab-triangle {
|
538 |
-
font-family: arial;
|
539 |
-
display: inline-block;
|
540 |
-
margin-right: 10px;
|
541 |
-
}
|
542 |
-
|
543 |
-
.wpstg-tab-header:focus {
|
544 |
-
color: #444;
|
545 |
-
outline: none;
|
546 |
-
box-shadow: none;
|
547 |
-
}
|
548 |
-
|
549 |
-
#wpstg-large-files {
|
550 |
-
display:none;
|
551 |
-
border: 1px dashed #ccc;
|
552 |
-
/*float: right;*/
|
553 |
-
padding: 10px 10px 10px;
|
554 |
-
margin-top:20px;
|
555 |
-
position: relative;
|
556 |
-
font-size:12px;
|
557 |
-
}
|
558 |
-
|
559 |
-
#wpstg-large-files h3 {
|
560 |
-
background: #fff;
|
561 |
-
margin: 0;
|
562 |
-
padding: 0 5px;
|
563 |
-
position: absolute;
|
564 |
-
top: -10px;
|
565 |
-
left: 5px;
|
566 |
-
}
|
567 |
-
|
568 |
-
/* tmp */
|
569 |
-
.wpstg-subdir {
|
570 |
-
display: none;
|
571 |
-
margin-left: 20px;
|
572 |
-
}
|
573 |
-
|
574 |
-
.wpstg-dir a.disabled {
|
575 |
-
color: #888;
|
576 |
-
cursor: default;
|
577 |
-
text-decoration: none;
|
578 |
-
}
|
579 |
-
|
580 |
-
.wpstg-check-subdirs {
|
581 |
-
display: inline-block;
|
582 |
-
margin-left: 10px;
|
583 |
-
}
|
584 |
-
|
585 |
-
.wpstg-notice-alert{
|
586 |
-
display:block;
|
587 |
-
background-color:#FFD0D0;
|
588 |
-
padding:20px;
|
589 |
-
border: 1px solid #fff;
|
590 |
-
max-width: 600px;
|
591 |
-
}
|
592 |
-
|
593 |
-
.wpstg-header{
|
594 |
-
font-weight: 400;
|
595 |
-
line-height: 1.6em;
|
596 |
-
font-size: 19px;
|
597 |
-
border-bottom: 1px solid #DFDFDF;
|
598 |
-
clear:both;
|
599 |
-
}
|
600 |
-
|
601 |
-
|
602 |
-
#wpstg-clone-label{
|
603 |
-
font-size: 14px;
|
604 |
-
font-weight: bold;
|
605 |
-
}
|
606 |
-
|
607 |
-
#wpstg-log-details{
|
608 |
-
height: 300px;
|
609 |
-
max-width: 700px;
|
610 |
-
overflow: scroll;
|
611 |
-
/*max-width: 650px;*/
|
612 |
-
font-family: monospace;
|
613 |
-
font-size: 12px;
|
614 |
-
line-height: 15px;
|
615 |
-
border: 1px solid #FFF;
|
616 |
-
background-color: black;
|
617 |
-
color: #c0c0c0;
|
618 |
-
padding:3px;
|
619 |
-
white-space: nowrap;
|
620 |
-
margin-top: 15px;
|
621 |
-
}
|
622 |
-
|
623 |
-
#wpstg-finished-result {
|
624 |
-
display:none;
|
625 |
-
}
|
626 |
-
|
627 |
-
#wpstg-remove-cloning {
|
628 |
-
background: #ff3428;
|
629 |
-
border-color: #e72f24;
|
630 |
-
margin-top: 5px;
|
631 |
-
}
|
632 |
-
|
633 |
-
#wpstg-success-notice{
|
634 |
-
padding: 10px;
|
635 |
-
background-color: white;
|
636 |
-
max-width: 900px;
|
637 |
-
border: 1px solid #ccc;
|
638 |
-
margin-top: 20px;
|
639 |
-
}
|
640 |
-
|
641 |
-
.wpstg_beta_notice {
|
642 |
-
margin-bottom:20px;
|
643 |
-
}
|
644 |
-
|
645 |
-
.wpstg-sysinfo {
|
646 |
-
width:700px;
|
647 |
-
height: 500px;
|
648 |
-
}
|
649 |
-
|
650 |
-
.form-table .col-title label {
|
651 |
-
font-weight: 600;
|
652 |
-
}
|
653 |
-
|
654 |
-
.form-table td:first-child {
|
655 |
-
width:30%;
|
656 |
-
}
|
657 |
-
|
658 |
-
|
659 |
-
.wpstg-share-button-container{
|
660 |
-
margin: 5px 0;
|
661 |
-
}
|
662 |
-
|
663 |
-
.wpstg-share-button-container p{
|
664 |
-
margin:0px 0 10px 0;
|
665 |
-
}
|
666 |
-
|
667 |
-
.wpstg-share-button {
|
668 |
-
display: inline-block;
|
669 |
-
}
|
670 |
-
|
671 |
-
.wpstg-share-button a{
|
672 |
-
text-decoration:none;
|
673 |
-
}
|
674 |
-
|
675 |
-
.wpstg-share-button .wpstg-share {
|
676 |
-
font-family:sans-serif;
|
677 |
-
font-weight:bold;
|
678 |
-
text-decoration:none;
|
679 |
-
text-align:center;
|
680 |
-
}
|
681 |
-
|
682 |
-
|
683 |
-
.wpstg-share-button .wpstg-share {
|
684 |
-
-webkit-border-radius:2px;
|
685 |
-
-moz-border-radius:2px;
|
686 |
-
border-radius:2px;
|
687 |
-
color:#FFF;
|
688 |
-
display:inline;
|
689 |
-
font-size:16px;
|
690 |
-
width:40px;
|
691 |
-
padding:4px 8px;
|
692 |
-
}
|
693 |
-
|
694 |
-
.wpstg-share-button-twitter .wpstg-share {
|
695 |
-
background-color:#00ABF0;
|
696 |
-
}
|
697 |
-
|
698 |
-
.wpstg-share-button-facebook .wpstg-share {
|
699 |
-
background-color:#3b5998;
|
700 |
-
}
|
701 |
-
|
702 |
-
.wpstg-share-button-googleplus .wpstg-share {
|
703 |
-
background-color:#F53424;
|
704 |
-
}
|
705 |
-
|
706 |
-
.wpstg-share-button-twitter .share:active,.wpstg-share-button-facebook .share:active,.wpstg-share-button-googleplus .share:active {
|
707 |
-
background-color:#353535;
|
708 |
-
}
|
709 |
-
|
710 |
-
#wpstg-check-space {
|
711 |
-
margin-left:8px;
|
712 |
-
}
|
713 |
-
|
714 |
-
/* welcome screen */
|
715 |
-
.wpstg-button.green {
|
716 |
-
display: inline-block;
|
717 |
-
background-color: #83c11f;
|
718 |
-
padding: 10px;
|
719 |
-
min-width: 170px;
|
720 |
-
color: white;
|
721 |
-
font-size: 16px;
|
722 |
-
text-decoration: none;
|
723 |
-
text-align: center;
|
724 |
-
margin-top: 20px;
|
725 |
-
}
|
726 |
-
#wpstg-welcome li {
|
727 |
-
font-size: 18px;
|
728 |
-
line-height: 29px;
|
729 |
-
position: relative;
|
730 |
-
padding-left: 23px;
|
731 |
-
list-style: none!important;
|
732 |
-
}
|
733 |
-
#wpstg-welcome {
|
734 |
-
margin-top:20px;
|
735 |
-
margin-right: 20px;
|
736 |
-
background-color: white;
|
737 |
-
}
|
738 |
-
.wpstg-heading-pro {
|
739 |
-
color: #0080ff;
|
740 |
-
font-weight: bold;
|
741 |
-
}
|
742 |
-
.wpstg-h2 {
|
743 |
-
margin-top: 0px;
|
744 |
-
margin-bottom: 1.2rem;
|
745 |
-
font-size: 30px;
|
746 |
-
line-height: 2.5rem;
|
747 |
-
}
|
748 |
-
#wpstg-welcome li:before {
|
749 |
-
width: 1em;
|
750 |
-
height: 100%;
|
751 |
-
background: url(data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) left .4em no-repeat;
|
752 |
-
background-size: contain;
|
753 |
-
content: "";
|
754 |
-
position: absolute;
|
755 |
-
top: 0;
|
756 |
-
left: 0;
|
757 |
-
color: #77b227;
|
758 |
-
}
|
759 |
-
.wpstg-h1 {
|
760 |
-
font-size: 2.75em;
|
761 |
-
margin-bottom: 1.35rem;
|
762 |
-
font-size: 2.5em;
|
763 |
-
line-height: 3.68rem;
|
764 |
-
letter-spacing: normal;
|
765 |
-
}
|
766 |
-
#wpstg-welcome h2 {
|
767 |
-
margin: 0 0 15px;
|
768 |
-
}
|
769 |
-
#wpstg-welcome .wpstg-footer {
|
770 |
-
clear: both;
|
771 |
-
margin-top: 20px;
|
772 |
-
font-style: italic;
|
773 |
-
}
|
774 |
-
|
775 |
-
.wpstg-staging-info {
|
776 |
-
clear:both;
|
777 |
-
float: right;
|
778 |
-
color:grey;
|
779 |
-
font-size: 12px;
|
780 |
-
}
|
781 |
-
|
782 |
-
.wpstg-bold{
|
783 |
-
font-weight: 600;
|
784 |
}
|
1 |
+
/**
|
2 |
+
* WPSTG Admin CSS
|
3 |
+
*
|
4 |
+
* @package WPSTG
|
5 |
+
* @subpackage Admin CSS
|
6 |
+
* @copyright Copyright (c) 2015, René Hermenau
|
7 |
+
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
8 |
+
*/
|
9 |
+
|
10 |
+
|
11 |
+
/* CSS for Tabs */
|
12 |
+
|
13 |
+
#tab_container ul {
|
14 |
+
/*height: 200px;*/
|
15 |
+
list-style: none;
|
16 |
+
margin: 0;
|
17 |
+
padding: 0;
|
18 |
+
background: #f1f1f1;
|
19 |
+
float: left;
|
20 |
+
/*list-style-type: square;*/
|
21 |
+
}
|
22 |
+
|
23 |
+
#tab_container ul li:first-child.selected-tab {
|
24 |
+
border-top: none;
|
25 |
+
}
|
26 |
+
|
27 |
+
#tab_container ul li a.selected-tab {
|
28 |
+
font-weight: bold;
|
29 |
+
text-decoration: none;
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
+
|
34 |
+
#tab_container .row{
|
35 |
+
padding-top:10px;
|
36 |
+
padding-bottom:12px;
|
37 |
+
}
|
38 |
+
|
39 |
+
#wpstg-tools .nav-tab-wrapper{
|
40 |
+
padding:0;
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
#tab_container .row label strong, #tab_container .row strong {
|
45 |
+
font-weight: bold;
|
46 |
+
}
|
47 |
+
|
48 |
+
.wpstg-tabs a {
|
49 |
+
padding:5px;
|
50 |
+
}
|
51 |
+
|
52 |
+
#tab_container > ul > li.wpstg-tabs.active {
|
53 |
+
background-color:white;
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
|
58 |
+
#wpstg_settingsgeneral_header .row:nth-child(3), #wpstg_settingsgeneral_header .row:nth-child(4){
|
59 |
+
display:none;
|
60 |
+
}
|
61 |
+
|
62 |
+
/* Layout of admin table and rows
|
63 |
+
*/
|
64 |
+
|
65 |
+
#tab_container .panel-container {
|
66 |
+
background: #FFF;
|
67 |
+
padding:0 20px 20px 20px;
|
68 |
+
overflow:auto;
|
69 |
+
}
|
70 |
+
|
71 |
+
#tab_container .form-table th {
|
72 |
+
vertical-align: top;
|
73 |
+
text-align: left;
|
74 |
+
padding: 20px 10px 20px 0;
|
75 |
+
line-height: 1.3;
|
76 |
+
font-weight: bold;
|
77 |
+
font-size: 14px;
|
78 |
+
color:#484848;
|
79 |
+
width: 30%;
|
80 |
+
}
|
81 |
+
|
82 |
+
#tab_container .form-table tr {
|
83 |
+
border-bottom: 1px solid #E7E7E7;
|
84 |
+
}
|
85 |
+
|
86 |
+
#tab_container span.description{
|
87 |
+
display: block;
|
88 |
+
font-weight: 400;
|
89 |
+
font-style: normal;
|
90 |
+
font-size: 13px;
|
91 |
+
margin-top: 7px;
|
92 |
+
color:#484848;
|
93 |
+
}
|
94 |
+
|
95 |
+
#tab_container .col-title{
|
96 |
+
color:#484848;
|
97 |
+
}
|
98 |
+
|
99 |
+
@media only screen and (max-width:680px) {
|
100 |
+
#tab_container ul {
|
101 |
+
float:none;
|
102 |
+
}
|
103 |
+
#tab_container .form-table tr > th {
|
104 |
+
width:100%;
|
105 |
+
}
|
106 |
+
#tab_container span.description{
|
107 |
+
font-size: 14px;
|
108 |
+
}
|
109 |
+
#tab_container .form-table tr > th, #tab_container .form-table tr > td {
|
110 |
+
padding:10px;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
#tab_container ul li {
|
115 |
+
margin-bottom:0;
|
116 |
+
}
|
117 |
+
|
118 |
+
#tab_container ul li a {
|
119 |
+
display: block;
|
120 |
+
padding:10px 4px 10px 14px;
|
121 |
+
border-width: 1px 0;
|
122 |
+
border-style: solid;
|
123 |
+
border-top-color:white;
|
124 |
+
border-bottom-color:#e7e7e7;
|
125 |
+
text-decoration: none;
|
126 |
+
color: #0097DF;
|
127 |
+
font-weight: bold;
|
128 |
+
}
|
129 |
+
#tab_container ul li a:hover {
|
130 |
+
background-color: #e5e5e5;
|
131 |
+
color:#777777;
|
132 |
+
}
|
133 |
+
|
134 |
+
|
135 |
+
.wp-staginglogo{
|
136 |
+
display: block;
|
137 |
+
font-size:16px;
|
138 |
+
padding-top:20px;
|
139 |
+
width:220px;
|
140 |
+
float:left;
|
141 |
+
}
|
142 |
+
|
143 |
+
.wpstg-version{
|
144 |
+
display: block;
|
145 |
+
padding-top:29px
|
146 |
+
}
|
147 |
+
|
148 |
+
|
149 |
+
.wpstg_admin .nav-tab {
|
150 |
+
color: #3C3C3C;
|
151 |
+
}
|
152 |
+
|
153 |
+
|
154 |
+
#tab_container table tbody tr:nth-child(1) > th > div {
|
155 |
+
font-size: 20px;
|
156 |
+
}
|
157 |
+
|
158 |
+
.wpstg_hidden{
|
159 |
+
display: none;
|
160 |
+
}
|
161 |
+
|
162 |
+
/* End layout of admin table and rows
|
163 |
+
*/
|
164 |
+
#mashtabcontainer > .mashtabs {
|
165 |
+
background-color: #ffffff;
|
166 |
+
}
|
167 |
+
|
168 |
+
#mashtabcontainer ul .active {
|
169 |
+
background-color: #00adef;
|
170 |
+
color: white;
|
171 |
+
border-bottom-color: #0098D2;
|
172 |
+
}
|
173 |
+
|
174 |
+
#mashtabcontainer ul .active:hover {
|
175 |
+
background-color: #00A4E2;
|
176 |
+
color: white;
|
177 |
+
border-bottom-color: #0098D2;
|
178 |
+
}
|
179 |
+
|
180 |
+
#mashtabcontainer ul li a {
|
181 |
+
padding: 10px 14px 10px 14px;
|
182 |
+
background-color: #f3f3f3
|
183 |
+
|
184 |
+
}
|
185 |
+
|
186 |
+
#mashtabcontainer .mashtab-container {
|
187 |
+
border: 0 solid #ececec;
|
188 |
+
}
|
189 |
+
|
190 |
+
/* Cloning workflow */
|
191 |
+
#wpstg-clonepage-wrapper {
|
192 |
+
margin-bottom: 20px;
|
193 |
+
/*width: 690px; */
|
194 |
+
}
|
195 |
+
|
196 |
+
@media screen and (min-width:1090px){
|
197 |
+
#wpstg-clonepage-wrapper {
|
198 |
+
float: left;
|
199 |
+
margin-bottom: 20px;
|
200 |
+
/*width: 690px;*/
|
201 |
+
}
|
202 |
+
.wpstg-sidebar{
|
203 |
+
display: none;
|
204 |
+
margin-left: 700px;
|
205 |
+
margin-top: 138px;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
.wpstg-sidebar{
|
210 |
+
display: none;
|
211 |
+
padding: 10px;
|
212 |
+
border: 1px solid #DFDFDF;
|
213 |
+
max-width: 250px;
|
214 |
+
height: 250px;
|
215 |
+
}
|
216 |
+
|
217 |
+
#wpstg-steps {
|
218 |
+
margin-top:30px;
|
219 |
+
}
|
220 |
+
|
221 |
+
#wpstg-steps li {
|
222 |
+
color: #444;
|
223 |
+
line-height: 20px;
|
224 |
+
padding-right:10px;
|
225 |
+
float:left;
|
226 |
+
}
|
227 |
+
|
228 |
+
|
229 |
+
.wpstg-step-num {
|
230 |
+
border: 1px solid #444;
|
231 |
+
border-radius: 3px;
|
232 |
+
display: inline-block;
|
233 |
+
width: 20px;
|
234 |
+
height: 20px;
|
235 |
+
text-align: center;
|
236 |
+
margin-right: 5px;
|
237 |
+
}
|
238 |
+
|
239 |
+
.wpstg-current-step {
|
240 |
+
font-weight: bold;
|
241 |
+
}
|
242 |
+
|
243 |
+
.wpstg-current-step .wpstg-step-num {
|
244 |
+
background: #444;
|
245 |
+
color: #eee;
|
246 |
+
}
|
247 |
+
|
248 |
+
.wpstg-clone {
|
249 |
+
border: 3px solid #ffffff;
|
250 |
+
margin-bottom: 5px;
|
251 |
+
padding: 5px 10px;
|
252 |
+
width: 300px;
|
253 |
+
position: relative;
|
254 |
+
overflow: hidden;
|
255 |
+
transition: border-color .2s ease-in-out;
|
256 |
+
background-color: #DDDDDD;
|
257 |
+
}
|
258 |
+
|
259 |
+
.wpstg-clone.active {
|
260 |
+
border-color: #1d94cf;;
|
261 |
+
}
|
262 |
+
|
263 |
+
.wpstg-clone-title {
|
264 |
+
display: inline-block;
|
265 |
+
font-size: 15px;
|
266 |
+
max-width: 130px;
|
267 |
+
text-decoration: none;
|
268 |
+
font-weight: bold;
|
269 |
+
color:#0285AE;
|
270 |
+
}
|
271 |
+
|
272 |
+
.wpstg-clone-action {
|
273 |
+
background: #ffffff;
|
274 |
+
border-left: 1px solid #ccc;
|
275 |
+
color: #bbb;
|
276 |
+
padding: 0 5px;
|
277 |
+
float: right;
|
278 |
+
text-decoration: none;
|
279 |
+
position: relative;
|
280 |
+
transition: color .2s ease-in-out;
|
281 |
+
}
|
282 |
+
|
283 |
+
.wpstg-remove-clone:hover {
|
284 |
+
color: #ef6d6d;
|
285 |
+
}
|
286 |
+
|
287 |
+
.wpstg-clone-action:last-child {
|
288 |
+
border: none;
|
289 |
+
}
|
290 |
+
|
291 |
+
.wpstg-clone:hover .wpstg-clone-action {
|
292 |
+
display: inline-block;
|
293 |
+
}
|
294 |
+
|
295 |
+
#wpstg-show-error-details:focus,
|
296 |
+
#wpstg-workflow .wpstg-clone-action {
|
297 |
+
outline: none;
|
298 |
+
box-shadow: none;
|
299 |
+
}
|
300 |
+
|
301 |
+
.wpstg-link-btn {
|
302 |
+
background: #45a1c9;
|
303 |
+
color: #fff;
|
304 |
+
display: inline-block;
|
305 |
+
padding: 5px 10px;
|
306 |
+
text-decoration: none;
|
307 |
+
vertical-align: baseline;
|
308 |
+
transition: all .2s ease-in-out;
|
309 |
+
}
|
310 |
+
|
311 |
+
.wpstg-link-btn:hover,
|
312 |
+
.wpstg-link-btn:focus {
|
313 |
+
color: #fff;
|
314 |
+
outline: none;
|
315 |
+
box-shadow: none;
|
316 |
+
}
|
317 |
+
|
318 |
+
#wpstg-workflow .wpstg-link-btn:active {
|
319 |
+
vertical-align: baseline;
|
320 |
+
}
|
321 |
+
|
322 |
+
.wpstg-link-btn[disabled] {
|
323 |
+
background: #777 !important;
|
324 |
+
pointer-events: none;
|
325 |
+
}
|
326 |
+
|
327 |
+
#wpstg-cancel-cloning {
|
328 |
+
background: #ff3428;
|
329 |
+
border-color: #e72f24;
|
330 |
+
margin-top: 5px;
|
331 |
+
}
|
332 |
+
|
333 |
+
#wpstg-cancel-cloning.success {
|
334 |
+
background: #64dd58;
|
335 |
+
border-color: #54bd4a;
|
336 |
+
}
|
337 |
+
|
338 |
+
#wpstg-error-wrapper,
|
339 |
+
#wpstg-error-details {
|
340 |
+
display:none;
|
341 |
+
padding-top: 10px;
|
342 |
+
font-size: 13px;
|
343 |
+
clear:both;
|
344 |
+
}
|
345 |
+
|
346 |
+
#wpstg-show-error-details {
|
347 |
+
display: inline-block;
|
348 |
+
margin-left: 5px;
|
349 |
+
color: #555;
|
350 |
+
text-decoration: none;
|
351 |
+
transition: color .2s ease-in-out;
|
352 |
+
}
|
353 |
+
|
354 |
+
#wpstg-show-error-details:hover {
|
355 |
+
color: #1d94cf;
|
356 |
+
}
|
357 |
+
|
358 |
+
#wpstg-error-details {
|
359 |
+
border-left: 5px solid #ef6d6d;
|
360 |
+
padding: 10px;
|
361 |
+
width: 500px;
|
362 |
+
}
|
363 |
+
|
364 |
+
#wpstg-home-link,
|
365 |
+
#wpstg-try-again {
|
366 |
+
display: none;
|
367 |
+
}
|
368 |
+
|
369 |
+
|
370 |
+
#wpstg-loader {
|
371 |
+
content: url('../img/loading.gif');
|
372 |
+
margin-top:-5px;
|
373 |
+
}
|
374 |
+
|
375 |
+
#wpstg-loader.wpstg-finished {
|
376 |
+
content:"Finished";
|
377 |
+
background-color:#00c89a;
|
378 |
+
color:white;
|
379 |
+
padding:2px;
|
380 |
+
margin-top:6px;
|
381 |
+
}
|
382 |
+
|
383 |
+
#wpstg-workflow {
|
384 |
+
position: relative;
|
385 |
+
clear:both;
|
386 |
+
padding-top:20px;
|
387 |
+
margin-right:20px;
|
388 |
+
float:left;
|
389 |
+
min-width: 500px;
|
390 |
+
border-right: 1px solid #DFDFDF;
|
391 |
+
min-height: 380px;
|
392 |
+
padding-right: 20px;
|
393 |
+
}
|
394 |
+
|
395 |
+
#wpstg-sidebar {
|
396 |
+
float: left;
|
397 |
+
max-width: 400px;
|
398 |
+
display: block;
|
399 |
+
}
|
400 |
+
|
401 |
+
@media screen and (max-width:1150px){
|
402 |
+
#wpstg-sidebar img{
|
403 |
+
margin-top: 30px;
|
404 |
+
}
|
405 |
+
}
|
406 |
+
|
407 |
+
#wpstg-workflow.loading::after,
|
408 |
+
#wpstg-removing-clone.loading::after {
|
409 |
+
background: rgba(255, 255, 255, .7);
|
410 |
+
content: 'Loading... may take a while for huge websites';
|
411 |
+
display: block;
|
412 |
+
width: 100%;
|
413 |
+
height: 100%;
|
414 |
+
font-size: 20px;
|
415 |
+
padding-top: 100px;
|
416 |
+
text-align: center;
|
417 |
+
position: absolute;
|
418 |
+
top: 0;
|
419 |
+
left: 0;
|
420 |
+
z-index: 99;
|
421 |
+
}
|
422 |
+
|
423 |
+
#wpstg-removing-clone.loading::after {
|
424 |
+
content: 'REMOVING' !important;
|
425 |
+
}
|
426 |
+
|
427 |
+
#wpstg-existing-clones,
|
428 |
+
#wpstg-removing-clone {
|
429 |
+
position: relative;
|
430 |
+
}
|
431 |
+
|
432 |
+
.wpstg-progress-bar {
|
433 |
+
max-width: 900px;
|
434 |
+
height: 27px;
|
435 |
+
padding: 0;
|
436 |
+
background-color: #d6d8d7;
|
437 |
+
}
|
438 |
+
|
439 |
+
.wpstg-progress {
|
440 |
+
background: #1d94cf;
|
441 |
+
width: 0;
|
442 |
+
height: 100%;
|
443 |
+
transition: width 1s;
|
444 |
+
color:white;
|
445 |
+
line-height:25px;
|
446 |
+
text-align:center;
|
447 |
+
}
|
448 |
+
|
449 |
+
#wpstg-new-clone-id.wpstg-error-input,
|
450 |
+
#wpstg-clone-path.wpstg-error-input {
|
451 |
+
border: 1px solid #ff4235;
|
452 |
+
box-shadow: 0 0 2px rgba(255, 66, 53, .8);
|
453 |
+
}
|
454 |
+
|
455 |
+
#wpstg-clone-path {
|
456 |
+
margin-left: 10px;
|
457 |
+
width: 350px;
|
458 |
+
}
|
459 |
+
|
460 |
+
.wpstg-error-msg {
|
461 |
+
color: #ff4235;
|
462 |
+
}
|
463 |
+
|
464 |
+
#wpstg-clone-id-error {
|
465 |
+
display: block;
|
466 |
+
text-align: right;
|
467 |
+
margin-right: 90px;
|
468 |
+
}
|
469 |
+
|
470 |
+
#wpstg-start-cloning + .wpstg-error-msg {
|
471 |
+
display: block;
|
472 |
+
margin-top: 5px;
|
473 |
+
}
|
474 |
+
|
475 |
+
.wpstg-size-info {
|
476 |
+
color: #999;
|
477 |
+
font-weight: normal;
|
478 |
+
position: relative;
|
479 |
+
left: 2px;
|
480 |
+
}
|
481 |
+
|
482 |
+
.wpstg-db-table .wpstg-size-info {
|
483 |
+
top: 2px;
|
484 |
+
}
|
485 |
+
|
486 |
+
#wpstg-workflow #wpstg-start-cloning {
|
487 |
+
display: inline-block;
|
488 |
+
margin-left: 5px;
|
489 |
+
font-size: 14px;
|
490 |
+
vertical-align: baseline;
|
491 |
+
}
|
492 |
+
|
493 |
+
/* Tabs */
|
494 |
+
.wpstg-tabs-wrapper {
|
495 |
+
max-width: 640px;
|
496 |
+
margin: 10px 0;
|
497 |
+
}
|
498 |
+
|
499 |
+
#wpstg-path-wrapper {
|
500 |
+
border-bottom: 2px dashed #ccc;
|
501 |
+
padding-bottom: 10px;
|
502 |
+
margin-bottom: 10px;
|
503 |
+
}
|
504 |
+
|
505 |
+
.wpstg-tabs-wrapper {
|
506 |
+
border: 1px solid #ddd;
|
507 |
+
border-right: none;
|
508 |
+
border-left: none;
|
509 |
+
}
|
510 |
+
|
511 |
+
.wpstg-tab-section {
|
512 |
+
border: 1px solid #ddd;
|
513 |
+
border-right: none;
|
514 |
+
border-left: none;
|
515 |
+
display: none;
|
516 |
+
padding: 20px;
|
517 |
+
}
|
518 |
+
|
519 |
+
.wpstg-tab-section::after {
|
520 |
+
display: block;
|
521 |
+
content: '';
|
522 |
+
clear: both;
|
523 |
+
}
|
524 |
+
|
525 |
+
.wpstg-tab-header {
|
526 |
+
border: 1px solid #ddd;
|
527 |
+
border-right: none;
|
528 |
+
border-left: none;
|
529 |
+
color: #444;
|
530 |
+
font-size: 16px;
|
531 |
+
font-weight: bolder;
|
532 |
+
display: block;
|
533 |
+
padding: 10px;;
|
534 |
+
text-decoration: none;
|
535 |
+
}
|
536 |
+
|
537 |
+
.wpstg-tab-triangle {
|
538 |
+
font-family: arial;
|
539 |
+
display: inline-block;
|
540 |
+
margin-right: 10px;
|
541 |
+
}
|
542 |
+
|
543 |
+
.wpstg-tab-header:focus {
|
544 |
+
color: #444;
|
545 |
+
outline: none;
|
546 |
+
box-shadow: none;
|
547 |
+
}
|
548 |
+
|
549 |
+
#wpstg-large-files {
|
550 |
+
display:none;
|
551 |
+
border: 1px dashed #ccc;
|
552 |
+
/*float: right;*/
|
553 |
+
padding: 10px 10px 10px;
|
554 |
+
margin-top:20px;
|
555 |
+
position: relative;
|
556 |
+
font-size:12px;
|
557 |
+
}
|
558 |
+
|
559 |
+
#wpstg-large-files h3 {
|
560 |
+
background: #fff;
|
561 |
+
margin: 0;
|
562 |
+
padding: 0 5px;
|
563 |
+
position: absolute;
|
564 |
+
top: -10px;
|
565 |
+
left: 5px;
|
566 |
+
}
|
567 |
+
|
568 |
+
/* tmp */
|
569 |
+
.wpstg-subdir {
|
570 |
+
display: none;
|
571 |
+
margin-left: 20px;
|
572 |
+
}
|
573 |
+
|
574 |
+
.wpstg-dir a.disabled {
|
575 |
+
color: #888;
|
576 |
+
cursor: default;
|
577 |
+
text-decoration: none;
|
578 |
+
}
|
579 |
+
|
580 |
+
.wpstg-check-subdirs {
|
581 |
+
display: inline-block;
|
582 |
+
margin-left: 10px;
|
583 |
+
}
|
584 |
+
|
585 |
+
.wpstg-notice-alert{
|
586 |
+
display:block;
|
587 |
+
background-color:#FFD0D0;
|
588 |
+
padding:20px;
|
589 |
+
border: 1px solid #fff;
|
590 |
+
max-width: 600px;
|
591 |
+
}
|
592 |
+
|
593 |
+
.wpstg-header{
|
594 |
+
font-weight: 400;
|
595 |
+
line-height: 1.6em;
|
596 |
+
font-size: 19px;
|
597 |
+
border-bottom: 1px solid #DFDFDF;
|
598 |
+
clear:both;
|
599 |
+
}
|
600 |
+
|
601 |
+
|
602 |
+
#wpstg-clone-label{
|
603 |
+
font-size: 14px;
|
604 |
+
font-weight: bold;
|
605 |
+
}
|
606 |
+
|
607 |
+
#wpstg-log-details{
|
608 |
+
height: 300px;
|
609 |
+
max-width: 700px;
|
610 |
+
overflow: scroll;
|
611 |
+
/*max-width: 650px;*/
|
612 |
+
font-family: monospace;
|
613 |
+
font-size: 12px;
|
614 |
+
line-height: 15px;
|
615 |
+
border: 1px solid #FFF;
|
616 |
+
background-color: black;
|
617 |
+
color: #c0c0c0;
|
618 |
+
padding:3px;
|
619 |
+
white-space: nowrap;
|
620 |
+
margin-top: 15px;
|
621 |
+
}
|
622 |
+
|
623 |
+
#wpstg-finished-result {
|
624 |
+
display:none;
|
625 |
+
}
|
626 |
+
|
627 |
+
#wpstg-remove-cloning {
|
628 |
+
background: #ff3428;
|
629 |
+
border-color: #e72f24;
|
630 |
+
margin-top: 5px;
|
631 |
+
}
|
632 |
+
|
633 |
+
#wpstg-success-notice{
|
634 |
+
padding: 10px;
|
635 |
+
background-color: white;
|
636 |
+
max-width: 900px;
|
637 |
+
border: 1px solid #ccc;
|
638 |
+
margin-top: 20px;
|
639 |
+
}
|
640 |
+
|
641 |
+
.wpstg_beta_notice {
|
642 |
+
margin-bottom:20px;
|
643 |
+
}
|
644 |
+
|
645 |
+
.wpstg-sysinfo {
|
646 |
+
width:700px;
|
647 |
+
height: 500px;
|
648 |
+
}
|
649 |
+
|
650 |
+
.form-table .col-title label {
|
651 |
+
font-weight: 600;
|
652 |
+
}
|
653 |
+
|
654 |
+
.form-table td:first-child {
|
655 |
+
width:30%;
|
656 |
+
}
|
657 |
+
|
658 |
+
|
659 |
+
.wpstg-share-button-container{
|
660 |
+
margin: 5px 0;
|
661 |
+
}
|
662 |
+
|
663 |
+
.wpstg-share-button-container p{
|
664 |
+
margin:0px 0 10px 0;
|
665 |
+
}
|
666 |
+
|
667 |
+
.wpstg-share-button {
|
668 |
+
display: inline-block;
|
669 |
+
}
|
670 |
+
|
671 |
+
.wpstg-share-button a{
|
672 |
+
text-decoration:none;
|
673 |
+
}
|
674 |
+
|
675 |
+
.wpstg-share-button .wpstg-share {
|
676 |
+
font-family:sans-serif;
|
677 |
+
font-weight:bold;
|
678 |
+
text-decoration:none;
|
679 |
+
text-align:center;
|
680 |
+
}
|
681 |
+
|
682 |
+
|
683 |
+
.wpstg-share-button .wpstg-share {
|
684 |
+
-webkit-border-radius:2px;
|
685 |
+
-moz-border-radius:2px;
|
686 |
+
border-radius:2px;
|
687 |
+
color:#FFF;
|
688 |
+
display:inline;
|
689 |
+
font-size:16px;
|
690 |
+
width:40px;
|
691 |
+
padding:4px 8px;
|
692 |
+
}
|
693 |
+
|
694 |
+
.wpstg-share-button-twitter .wpstg-share {
|
695 |
+
background-color:#00ABF0;
|
696 |
+
}
|
697 |
+
|
698 |
+
.wpstg-share-button-facebook .wpstg-share {
|
699 |
+
background-color:#3b5998;
|
700 |
+
}
|
701 |
+
|
702 |
+
.wpstg-share-button-googleplus .wpstg-share {
|
703 |
+
background-color:#F53424;
|
704 |
+
}
|
705 |
+
|
706 |
+
.wpstg-share-button-twitter .share:active,.wpstg-share-button-facebook .share:active,.wpstg-share-button-googleplus .share:active {
|
707 |
+
background-color:#353535;
|
708 |
+
}
|
709 |
+
|
710 |
+
#wpstg-check-space {
|
711 |
+
margin-left:8px;
|
712 |
+
}
|
713 |
+
|
714 |
+
/* welcome screen */
|
715 |
+
.wpstg-button.green {
|
716 |
+
display: inline-block;
|
717 |
+
background-color: #83c11f;
|
718 |
+
padding: 10px;
|
719 |
+
min-width: 170px;
|
720 |
+
color: white;
|
721 |
+
font-size: 16px;
|
722 |
+
text-decoration: none;
|
723 |
+
text-align: center;
|
724 |
+
margin-top: 20px;
|
725 |
+
}
|
726 |
+
#wpstg-welcome li {
|
727 |
+
font-size: 18px;
|
728 |
+
line-height: 29px;
|
729 |
+
position: relative;
|
730 |
+
padding-left: 23px;
|
731 |
+
list-style: none!important;
|
732 |
+
}
|
733 |
+
#wpstg-welcome {
|
734 |
+
margin-top:20px;
|
735 |
+
margin-right: 20px;
|
736 |
+
background-color: white;
|
737 |
+
}
|
738 |
+
.wpstg-heading-pro {
|
739 |
+
color: #0080ff;
|
740 |
+
font-weight: bold;
|
741 |
+
}
|
742 |
+
.wpstg-h2 {
|
743 |
+
margin-top: 0px;
|
744 |
+
margin-bottom: 1.2rem;
|
745 |
+
font-size: 30px;
|
746 |
+
line-height: 2.5rem;
|
747 |
+
}
|
748 |
+
#wpstg-welcome li:before {
|
749 |
+
width: 1em;
|
750 |
+
height: 100%;
|
751 |
+
background: url(data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) left .4em no-repeat;
|
752 |
+
background-size: contain;
|
753 |
+
content: "";
|
754 |
+
position: absolute;
|
755 |
+
top: 0;
|
756 |
+
left: 0;
|
757 |
+
color: #77b227;
|
758 |
+
}
|
759 |
+
.wpstg-h1 {
|
760 |
+
font-size: 2.75em;
|
761 |
+
margin-bottom: 1.35rem;
|
762 |
+
font-size: 2.5em;
|
763 |
+
line-height: 3.68rem;
|
764 |
+
letter-spacing: normal;
|
765 |
+
}
|
766 |
+
#wpstg-welcome h2 {
|
767 |
+
margin: 0 0 15px;
|
768 |
+
}
|
769 |
+
#wpstg-welcome .wpstg-footer {
|
770 |
+
clear: both;
|
771 |
+
margin-top: 20px;
|
772 |
+
font-style: italic;
|
773 |
+
}
|
774 |
+
|
775 |
+
.wpstg-staging-info {
|
776 |
+
clear:both;
|
777 |
+
float: right;
|
778 |
+
color:grey;
|
779 |
+
font-size: 12px;
|
780 |
+
}
|
781 |
+
|
782 |
+
.wpstg-bold{
|
783 |
+
font-weight: 600;
|
784 |
}
|
apps/Backend/public/js/wpstg-admin-rating.js
CHANGED
@@ -1,32 +1,32 @@
|
|
1 |
-
jQuery(document).ready(function ($) {
|
2 |
-
$(".wpstg_hide_rating").click(function (e) {
|
3 |
-
e.preventDefault();
|
4 |
-
|
5 |
-
$.ajax({
|
6 |
-
url: ajaxurl,
|
7 |
-
type: "POST",
|
8 |
-
data: {action: "wpstg_hide_rating"},
|
9 |
-
error: function (xhr, textStatus, errorThrown) {
|
10 |
-
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
11 |
-
console.log(textStatus);
|
12 |
-
|
13 |
-
|
14 |
-
alert(
|
15 |
-
"Unknown error"
|
16 |
-
);
|
17 |
-
},
|
18 |
-
success: function (data) {
|
19 |
-
$(".wpstg_fivestar").slideUp("fast");
|
20 |
-
return true;
|
21 |
-
},
|
22 |
-
statusCode: {
|
23 |
-
404: function () {
|
24 |
-
alert("Something went wrong; can't find ajax request URL!");
|
25 |
-
},
|
26 |
-
500: function () {
|
27 |
-
alert("Something went wrong; internal server error while processing the request!");
|
28 |
-
}
|
29 |
-
}
|
30 |
-
});
|
31 |
-
});
|
32 |
});
|
1 |
+
jQuery(document).ready(function ($) {
|
2 |
+
$(".wpstg_hide_rating").click(function (e) {
|
3 |
+
e.preventDefault();
|
4 |
+
|
5 |
+
$.ajax({
|
6 |
+
url: ajaxurl,
|
7 |
+
type: "POST",
|
8 |
+
data: {action: "wpstg_hide_rating"},
|
9 |
+
error: function (xhr, textStatus, errorThrown) {
|
10 |
+
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
11 |
+
console.log(textStatus);
|
12 |
+
|
13 |
+
|
14 |
+
alert(
|
15 |
+
"Unknown error"
|
16 |
+
);
|
17 |
+
},
|
18 |
+
success: function (data) {
|
19 |
+
$(".wpstg_fivestar").slideUp("fast");
|
20 |
+
return true;
|
21 |
+
},
|
22 |
+
statusCode: {
|
23 |
+
404: function () {
|
24 |
+
alert("Something went wrong; can't find ajax request URL!");
|
25 |
+
},
|
26 |
+
500: function () {
|
27 |
+
alert("Something went wrong; internal server error while processing the request!");
|
28 |
+
}
|
29 |
+
}
|
30 |
+
});
|
31 |
+
});
|
32 |
});
|
apps/Backend/public/js/wpstg-admin.js
CHANGED
@@ -1,1261 +1,1178 @@
|
|
1 |
-
"use strict";
|
2 |
-
|
3 |
-
var WPStaging = (function ($)
|
4 |
-
{
|
5 |
-
var that = {
|
6 |
-
isCancelled: false,
|
7 |
-
isFinished: false,
|
8 |
-
getLogs: false
|
9 |
-
},
|
10 |
-
cache = {elements: []},
|
11 |
-
timeout, ajaxSpinner;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Get / Set Cache for Selector
|
15 |
-
* @param {String} selector
|
16 |
-
* @returns {*}
|
17 |
-
*/
|
18 |
-
cache.get = function (selector)
|
19 |
-
{
|
20 |
-
// It is already cached!
|
21 |
-
if ($.inArray(selector, cache.elements) !== -1)
|
22 |
-
{
|
23 |
-
return cache.elements[selector];
|
24 |
-
}
|
25 |
-
|
26 |
-
// Create cache and return
|
27 |
-
cache.elements[selector] = jQuery(selector);
|
28 |
-
|
29 |
-
return cache.elements[selector];
|
30 |
-
};
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Refreshes given cache
|
34 |
-
* @param {String} selector
|
35 |
-
*/
|
36 |
-
cache.refresh = function (selector)
|
37 |
-
{
|
38 |
-
selector.elements[selector] = jQuery(selector);
|
39 |
-
};
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Show and Log Error Message
|
43 |
-
* @param {String} message
|
44 |
-
*/
|
45 |
-
var showError = function (message)
|
46 |
-
{
|
47 |
-
cache.get("#wpstg-try-again").css("display", "inline-block");
|
48 |
-
cache.get("#wpstg-cancel-cloning").text("Reset");
|
49 |
-
cache.get("#wpstg-cloning-result").text("Fail");
|
50 |
-
cache.get("#wpstg-error-wrapper").show();
|
51 |
-
cache.get("#wpstg-error-details")
|
52 |
-
.show()
|
53 |
-
.html(message);
|
54 |
-
cache.get("#wpstg-removing-clone").removeClass("loading");
|
55 |
-
cache.get("#wpstg-loader").hide();
|
56 |
-
};
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Common Elements
|
60 |
-
*/
|
61 |
-
var elements = function ()
|
62 |
-
{
|
63 |
-
var $workFlow = cache.get("#wpstg-workflow"),
|
64 |
-
isAllChecked = true,
|
65 |
-
urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
|
66 |
-
timer;
|
67 |
-
|
68 |
-
if (2 < window.devicePixelRatio)
|
69 |
-
{
|
70 |
-
urlSpinner += "-2x";
|
71 |
-
}
|
72 |
-
|
73 |
-
urlSpinner += ".gif";
|
74 |
-
|
75 |
-
ajaxSpinner = "<img src=''" + urlSpinner + "' alt='' class='ajax-spinner general-spinner' />";
|
76 |
-
|
77 |
-
$workFlow
|
78 |
-
// Check / Un-check Database Tables
|
79 |
-
.on("click", ".wpstg-button-unselect", function (e) {
|
80 |
-
e.preventDefault();
|
81 |
-
|
82 |
-
if (false === isAllChecked)
|
83 |
-
{
|
84 |
-
cache.get(".wpstg-db-table-checkboxes").prop("checked", true);
|
85 |
-
cache.get(".wpstg-button-unselect").text("Un-check All");
|
86 |
-
isAllChecked = true;
|
87 |
-
}
|
88 |
-
else
|
89 |
-
{
|
90 |
-
cache.get(".wpstg-db-table-checkboxes").prop("checked", false);
|
91 |
-
cache.get(".wpstg-button-unselect").text("Check All");
|
92 |
-
isAllChecked = false;
|
93 |
-
}
|
94 |
-
})
|
95 |
-
.on("click", ".wpstg-button-select", function (e) {
|
96 |
-
console.log('test1');
|
97 |
-
|
98 |
-
e.preventDefault();
|
99 |
-
|
100 |
-
$(".wpstg-db-table input").each(function () {
|
101 |
-
if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
102 |
-
$(this).prop("checked", true);
|
103 |
-
} else {
|
104 |
-
$(this).prop("checked", false);
|
105 |
-
|
106 |
-
}
|
107 |
-
});
|
108 |
-
})
|
109 |
-
// Expand Directories
|
110 |
-
.on("click", ".wpstg-expand-dirs", function (e) {
|
111 |
-
e.preventDefault();
|
112 |
-
|
113 |
-
var $this = $(this);
|
114 |
-
|
115 |
-
if (!$this.hasClass("disabled"))
|
116 |
-
{
|
117 |
-
$this.siblings(".wpstg-subdir").slideToggle();
|
118 |
-
}
|
119 |
-
})
|
120 |
-
// When a Directory is Selected
|
121 |
-
.on("change", ".wpstg-check-dir", function () {
|
122 |
-
var $directory = $(this).parent(".wpstg-dir");
|
123 |
-
|
124 |
-
if (this.checked)
|
125 |
-
{
|
126 |
-
$directory.parents(".wpstg-dir").children(".wpstg-check-dir").prop("checked", true);
|
127 |
-
$directory.find(".wpstg-expand-dirs").removeClass("disabled");
|
128 |
-
$directory.find(".wpstg-subdir .wpstg-check-dir").prop("checked", true);
|
129 |
-
}
|
130 |
-
else
|
131 |
-
{
|
132 |
-
$directory.find(".wpstg-dir .wpstg-check-dir").prop("checked", false);
|
133 |
-
$directory.find(".wpstg-expand-dirs, .wpstg-check-subdirs").addClass("disabled");
|
134 |
-
$directory.find(".wpstg-check-subdirs").data("action", "check").text("check");
|
135 |
-
$directory.children(".wpstg-subdir").slideUp();
|
136 |
-
}
|
137 |
-
})
|
138 |
-
// Check the max length of the clone name and if the clone name already exists
|
139 |
-
.on("keyup", "#wpstg-new-clone-id", function () {
|
140 |
-
|
141 |
-
// This request was already sent, clear it up!
|
142 |
-
if ("number" === typeof (timer))
|
143 |
-
{
|
144 |
-
clearInterval(timer);
|
145 |
-
}
|
146 |
-
|
147 |
-
var cloneID = this.value;
|
148 |
-
|
149 |
-
timer = setTimeout(
|
150 |
-
function () {
|
151 |
-
ajax(
|
152 |
-
{
|
153 |
-
action: "wpstg_check_clone",
|
154 |
-
cloneID: cloneID
|
155 |
-
},
|
156 |
-
function (response)
|
157 |
-
{
|
158 |
-
if (response.status === "success")
|
159 |
-
{
|
160 |
-
cache.get("#wpstg-new-clone-id").removeClass("wpstg-error-input");
|
161 |
-
cache.get("#wpstg-start-cloning").removeAttr("disabled");
|
162 |
-
cache.get("#wpstg-clone-id-error").text('').hide();
|
163 |
-
}
|
164 |
-
else
|
165 |
-
{
|
166 |
-
cache.get("#wpstg-new-clone-id").addClass("wpstg-error-input");
|
167 |
-
cache.get("#wpstg-start-cloning").prop("disabled", true);
|
168 |
-
cache.get("#wpstg-clone-id-error").text(response.message).show();
|
169 |
-
}
|
170 |
-
}
|
171 |
-
);
|
172 |
-
},
|
173 |
-
500
|
174 |
-
);
|
175 |
-
})
|
176 |
-
// Restart cloning process
|
177 |
-
.on("click", "#wpstg-start-cloning", function () {
|
178 |
-
that.isCancelled = false;
|
179 |
-
that.getLogs = false;
|
180 |
-
})
|
181 |
-
// Display logs
|
182 |
-
// .on("click", "#wpstg-show-log-button", function (e) {
|
183 |
-
// e.preventDefault();
|
184 |
-
// var $logDetails = cache.get("#wpstg-log-details");
|
185 |
-
//
|
186 |
-
// $logDetails.toggle();
|
187 |
-
//
|
188 |
-
// logscroll();
|
189 |
-
//
|
190 |
-
// that.getLogs = (false === that.getLogs);
|
191 |
-
// });
|
192 |
-
|
193 |
-
cloneActions();
|
194 |
-
};
|
195 |
-
|
196 |
-
|
197 |
-
/**
|
198 |
-
* Clone actions
|
199 |
-
*/
|
200 |
-
var cloneActions = function ()
|
201 |
-
{
|
202 |
-
var $workFlow = cache.get("#wpstg-workflow");
|
203 |
-
|
204 |
-
$workFlow
|
205 |
-
// Cancel cloning
|
206 |
-
.on("click", "#wpstg-cancel-cloning", function () {
|
207 |
-
if (!confirm("Are you sure you want to cancel cloning process?"))
|
208 |
-
{
|
209 |
-
return false;
|
210 |
-
}
|
211 |
-
|
212 |
-
var $this = $(this);
|
213 |
-
|
214 |
-
$("#wpstg-try-again, #wpstg-home-link").hide();
|
215 |
-
$this.prop("disabled", true);
|
216 |
-
|
217 |
-
that.isCancelled = true;
|
218 |
-
|
219 |
-
$("#wpstg-cloning-result").text("Please wait...this can take up a while.");
|
220 |
-
$("#wpstg-loader, #wpstg-show-log-button").hide();
|
221 |
-
|
222 |
-
$this.parent().append(ajaxSpinner);
|
223 |
-
|
224 |
-
cancelCloning();
|
225 |
-
})
|
226 |
-
// Cancel update cloning
|
227 |
-
.on("click", "#wpstg-cancel-cloning-update", function () {
|
228 |
-
if (!confirm("Are you sure you want to cancel clone updating process?"))
|
229 |
-
{
|
230 |
-
return false;
|
231 |
-
}
|
232 |
-
|
233 |
-
var $this = $(this);
|
234 |
-
|
235 |
-
$("#wpstg-try-again, #wpstg-home-link").hide();
|
236 |
-
$this.prop("disabled", true);
|
237 |
-
|
238 |
-
that.isCancelled = true;
|
239 |
-
|
240 |
-
$("#wpstg-cloning-result").text("Please wait...this can take up a while.");
|
241 |
-
$("#wpstg-loader, #wpstg-show-log-button").hide();
|
242 |
-
|
243 |
-
$this.parent().append(ajaxSpinner);
|
244 |
-
|
245 |
-
cancelCloningUpdate();
|
246 |
-
})
|
247 |
-
// Delete clone - confirmation
|
248 |
-
.on("click", ".wpstg-remove-clone[data-clone]", function (e) {
|
249 |
-
e.preventDefault();
|
250 |
-
|
251 |
-
var $existingClones = cache.get("#wpstg-existing-clones");
|
252 |
-
|
253 |
-
$workFlow.removeClass('active');
|
254 |
-
|
255 |
-
cache.get("#wpstg-loader").show();
|
256 |
-
|
257 |
-
ajax(
|
258 |
-
{
|
259 |
-
action: "wpstg_confirm_delete_clone",
|
260 |
-
nonce: wpstg.nonce,
|
261 |
-
clone: $(this).data("clone")
|
262 |
-
},
|
263 |
-
function (response)
|
264 |
-
{
|
265 |
-
cache.get("#wpstg-removing-clone").html(response);
|
266 |
-
|
267 |
-
$existingClones.children("img").remove();
|
268 |
-
|
269 |
-
cache.get("#wpstg-loader").hide();
|
270 |
-
},
|
271 |
-
"HTML"
|
272 |
-
);
|
273 |
-
})
|
274 |
-
// Delete clone - confirmed
|
275 |
-
.on("click", "#wpstg-remove-clone", function (e) {
|
276 |
-
e.preventDefault();
|
277 |
-
|
278 |
-
cache.get("#wpstg-removing-clone").addClass("loading");
|
279 |
-
|
280 |
-
cache.get("#wpstg-loader").show();
|
281 |
-
|
282 |
-
deleteClone($(this).data("clone"));
|
283 |
-
})
|
284 |
-
// Cancel deleting clone
|
285 |
-
.on("click", "#wpstg-cancel-removing", function (e) {
|
286 |
-
e.preventDefault();
|
287 |
-
$(".wpstg-clone").removeClass("active");
|
288 |
-
cache.get("#wpstg-removing-clone").html('');
|
289 |
-
})
|
290 |
-
// Update
|
291 |
-
.on("click", ".wpstg-execute-clone", function (e) {
|
292 |
-
e.preventDefault();
|
293 |
-
|
294 |
-
if (!confirm("Are you sure you want to update the staging site? All your staging site modifications will be overwritten with the data from the live site. So make sure that your live site is up to date."))
|
295 |
-
{
|
296 |
-
return false;
|
297 |
-
}
|
298 |
-
|
299 |
-
var clone = $(this).data("clone");
|
300 |
-
|
301 |
-
$workFlow.addClass("loading");
|
302 |
-
|
303 |
-
ajax(
|
304 |
-
{
|
305 |
-
action: "wpstg_scanning",
|
306 |
-
clone: clone,
|
307 |
-
nonce: wpstg.nonce
|
308 |
-
},
|
309 |
-
function (response)
|
310 |
-
{
|
311 |
-
if (response.length < 1)
|
312 |
-
{
|
313 |
-
showError("Something went wrong, please try again");
|
314 |
-
}
|
315 |
-
|
316 |
-
$workFlow.removeClass("loading").html(response);
|
317 |
-
|
318 |
-
cache.get(".wpstg-current-step")
|
319 |
-
.removeClass("wpstg-current-step")
|
320 |
-
.next("li")
|
321 |
-
.addClass("wpstg-current-step");
|
322 |
-
},
|
323 |
-
"HTML"
|
324 |
-
);
|
325 |
-
});
|
326 |
-
};
|
327 |
-
|
328 |
-
|
329 |
-
/**
|
330 |
-
* Ajax Requests
|
331 |
-
* @param {Object} data
|
332 |
-
* @param {Function} callback
|
333 |
-
* @param {String} dataType
|
334 |
-
* @param {Boolean} showErrors
|
335 |
-
*/
|
336 |
-
var ajax = function (data, callback, dataType, showErrors)
|
337 |
-
{
|
338 |
-
if ("undefined" === typeof (dataType))
|
339 |
-
{
|
340 |
-
dataType = "json";
|
341 |
-
}
|
342 |
-
|
343 |
-
if (false !== showErrors)
|
344 |
-
{
|
345 |
-
showErrors = true;
|
346 |
-
}
|
347 |
-
|
348 |
-
$.ajax({
|
349 |
-
url: ajaxurl,
|
350 |
-
type: "POST",
|
351 |
-
dataType: dataType,
|
352 |
-
cache: false,
|
353 |
-
data: data,
|
354 |
-
error: function (xhr, textStatus, errorThrown) {
|
355 |
-
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
356 |
-
console.log(textStatus);
|
357 |
-
|
358 |
-
if (false === showErrors)
|
359 |
-
{
|
360 |
-
return false;
|
361 |
-
}
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
"
|
366 |
-
"
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
ajax
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
.
|
439 |
-
.
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
cache.get("#wpstg-loader").
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
*
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
/**
|
473 |
-
* Get
|
474 |
-
* @returns {Array}
|
475 |
-
*/
|
476 |
-
var
|
477 |
-
{
|
478 |
-
var
|
479 |
-
|
480 |
-
$(".wpstg-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
}
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
//
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
//
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
//
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
//
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
//
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
//
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
//
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
//
|
917 |
-
|
918 |
-
|
919 |
-
//
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
);
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
function () {
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
|
1163 |
-
|
1164 |
-
|
1165 |
-
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
cache.get("#wpstg-loader").hide();
|
1179 |
-
return false;
|
1180 |
-
}
|
1181 |
-
|
1182 |
-
ajax(
|
1183 |
-
{
|
1184 |
-
action: "wpstg_clone_finish",
|
1185 |
-
nonce: wpstg.nonce
|
1186 |
-
},
|
1187 |
-
function (response)
|
1188 |
-
{
|
1189 |
-
// Invalid response
|
1190 |
-
if ("object" !== typeof (response))
|
1191 |
-
{
|
1192 |
-
showError(
|
1193 |
-
"Couldn't finish the cloning process properly. " +
|
1194 |
-
"Your clone has been copied but failed to do clean up and " +
|
1195 |
-
"saving its records to the database." +
|
1196 |
-
"Please contact support and provide your logs."
|
1197 |
-
);
|
1198 |
-
|
1199 |
-
return;
|
1200 |
-
}
|
1201 |
-
|
1202 |
-
// Add Log
|
1203 |
-
if ("undefined" !== typeof (response.last_msg))
|
1204 |
-
{
|
1205 |
-
getLogs(response.last_msg);
|
1206 |
-
}
|
1207 |
-
|
1208 |
-
console.log("Cloning process finished");
|
1209 |
-
|
1210 |
-
var $link1 = cache.get("#wpstg-clone-url-1");
|
1211 |
-
var $link = cache.get("#wpstg-clone-url");
|
1212 |
-
|
1213 |
-
cache.get("#wpstg_staging_name").html(that.data.cloneID);
|
1214 |
-
cache.get("#wpstg-finished-result").show();
|
1215 |
-
cache.get("#wpstg-cancel-cloning").prop("disabled", true);
|
1216 |
-
cache.get("#wpstg-cancel-cloning-update").prop("disabled", true);
|
1217 |
-
// $link1.attr("href", $link1.attr("href") + '/' + response.directoryName);
|
1218 |
-
// $link1.append('/' + response.directoryName);
|
1219 |
-
// $link.attr("href", $link.attr("href") + '/' + response.directoryName);
|
1220 |
-
$link1.attr("href", response.url);
|
1221 |
-
$link.attr("href", response.url);
|
1222 |
-
cache.get("#wpstg-remove-clone").data("clone", that.data.cloneID);
|
1223 |
-
|
1224 |
-
// Finished
|
1225 |
-
that.isFinished = true;
|
1226 |
-
|
1227 |
-
finish();
|
1228 |
-
}
|
1229 |
-
);
|
1230 |
-
}
|
1231 |
-
});
|
1232 |
-
|
1233 |
-
|
1234 |
-
/**
|
1235 |
-
* Initiation
|
1236 |
-
* @type {Function}
|
1237 |
-
*/
|
1238 |
-
that.init = (function () {
|
1239 |
-
loadOverview();
|
1240 |
-
elements();
|
1241 |
-
//startUpdate();
|
1242 |
-
stepButtons();
|
1243 |
-
tabs();
|
1244 |
-
//optimizer();
|
1245 |
-
});
|
1246 |
-
|
1247 |
-
/**
|
1248 |
-
* Ajax call
|
1249 |
-
* @type {ajax}
|
1250 |
-
*/
|
1251 |
-
that.ajax = ajax;
|
1252 |
-
that.showError = showError;
|
1253 |
-
that.getLogs = getLogs;
|
1254 |
-
that.loadOverview = loadOverview;
|
1255 |
-
|
1256 |
-
return that;
|
1257 |
-
})(jQuery);
|
1258 |
-
|
1259 |
-
jQuery(document).ready(function () {
|
1260 |
-
WPStaging.init();
|
1261 |
});
|
1 |
+
"use strict";
|
2 |
+
|
3 |
+
var WPStaging = (function ($)
|
4 |
+
{
|
5 |
+
var that = {
|
6 |
+
isCancelled: false,
|
7 |
+
isFinished: false,
|
8 |
+
getLogs: false
|
9 |
+
},
|
10 |
+
cache = {elements: []},
|
11 |
+
timeout, ajaxSpinner;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Get / Set Cache for Selector
|
15 |
+
* @param {String} selector
|
16 |
+
* @returns {*}
|
17 |
+
*/
|
18 |
+
cache.get = function (selector)
|
19 |
+
{
|
20 |
+
// It is already cached!
|
21 |
+
if ($.inArray(selector, cache.elements) !== -1)
|
22 |
+
{
|
23 |
+
return cache.elements[selector];
|
24 |
+
}
|
25 |
+
|
26 |
+
// Create cache and return
|
27 |
+
cache.elements[selector] = jQuery(selector);
|
28 |
+
|
29 |
+
return cache.elements[selector];
|
30 |
+
};
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Refreshes given cache
|
34 |
+
* @param {String} selector
|
35 |
+
*/
|
36 |
+
cache.refresh = function (selector)
|
37 |
+
{
|
38 |
+
selector.elements[selector] = jQuery(selector);
|
39 |
+
};
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Show and Log Error Message
|
43 |
+
* @param {String} message
|
44 |
+
*/
|
45 |
+
var showError = function (message)
|
46 |
+
{
|
47 |
+
cache.get("#wpstg-try-again").css("display", "inline-block");
|
48 |
+
cache.get("#wpstg-cancel-cloning").text("Reset");
|
49 |
+
cache.get("#wpstg-cloning-result").text("Fail");
|
50 |
+
cache.get("#wpstg-error-wrapper").show();
|
51 |
+
cache.get("#wpstg-error-details")
|
52 |
+
.show()
|
53 |
+
.html(message);
|
54 |
+
cache.get("#wpstg-removing-clone").removeClass("loading");
|
55 |
+
cache.get("#wpstg-loader").hide();
|
56 |
+
};
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Common Elements
|
60 |
+
*/
|
61 |
+
var elements = function ()
|
62 |
+
{
|
63 |
+
var $workFlow = cache.get("#wpstg-workflow"),
|
64 |
+
isAllChecked = true,
|
65 |
+
urlSpinner = ajaxurl.replace("/admin-ajax.php", '') + "/images/spinner",
|
66 |
+
timer;
|
67 |
+
|
68 |
+
if (2 < window.devicePixelRatio)
|
69 |
+
{
|
70 |
+
urlSpinner += "-2x";
|
71 |
+
}
|
72 |
+
|
73 |
+
urlSpinner += ".gif";
|
74 |
+
|
75 |
+
ajaxSpinner = "<img src=''" + urlSpinner + "' alt='' class='ajax-spinner general-spinner' />";
|
76 |
+
|
77 |
+
$workFlow
|
78 |
+
// Check / Un-check Database Tables
|
79 |
+
.on("click", ".wpstg-button-unselect", function (e) {
|
80 |
+
e.preventDefault();
|
81 |
+
|
82 |
+
if (false === isAllChecked)
|
83 |
+
{
|
84 |
+
cache.get(".wpstg-db-table-checkboxes").prop("checked", true);
|
85 |
+
cache.get(".wpstg-button-unselect").text("Un-check All");
|
86 |
+
isAllChecked = true;
|
87 |
+
}
|
88 |
+
else
|
89 |
+
{
|
90 |
+
cache.get(".wpstg-db-table-checkboxes").prop("checked", false);
|
91 |
+
cache.get(".wpstg-button-unselect").text("Check All");
|
92 |
+
isAllChecked = false;
|
93 |
+
}
|
94 |
+
})
|
95 |
+
.on("click", ".wpstg-button-select", function (e) {
|
96 |
+
console.log('test1');
|
97 |
+
|
98 |
+
e.preventDefault();
|
99 |
+
|
100 |
+
$(".wpstg-db-table input").each(function () {
|
101 |
+
if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
102 |
+
$(this).prop("checked", true);
|
103 |
+
} else {
|
104 |
+
$(this).prop("checked", false);
|
105 |
+
|
106 |
+
}
|
107 |
+
});
|
108 |
+
})
|
109 |
+
// Expand Directories
|
110 |
+
.on("click", ".wpstg-expand-dirs", function (e) {
|
111 |
+
e.preventDefault();
|
112 |
+
|
113 |
+
var $this = $(this);
|
114 |
+
|
115 |
+
if (!$this.hasClass("disabled"))
|
116 |
+
{
|
117 |
+
$this.siblings(".wpstg-subdir").slideToggle();
|
118 |
+
}
|
119 |
+
})
|
120 |
+
// When a Directory is Selected
|
121 |
+
.on("change", ".wpstg-check-dir", function () {
|
122 |
+
var $directory = $(this).parent(".wpstg-dir");
|
123 |
+
|
124 |
+
if (this.checked)
|
125 |
+
{
|
126 |
+
$directory.parents(".wpstg-dir").children(".wpstg-check-dir").prop("checked", true);
|
127 |
+
$directory.find(".wpstg-expand-dirs").removeClass("disabled");
|
128 |
+
$directory.find(".wpstg-subdir .wpstg-check-dir").prop("checked", true);
|
129 |
+
}
|
130 |
+
else
|
131 |
+
{
|
132 |
+
$directory.find(".wpstg-dir .wpstg-check-dir").prop("checked", false);
|
133 |
+
$directory.find(".wpstg-expand-dirs, .wpstg-check-subdirs").addClass("disabled");
|
134 |
+
$directory.find(".wpstg-check-subdirs").data("action", "check").text("check");
|
135 |
+
$directory.children(".wpstg-subdir").slideUp();
|
136 |
+
}
|
137 |
+
})
|
138 |
+
// Check the max length of the clone name and if the clone name already exists
|
139 |
+
.on("keyup", "#wpstg-new-clone-id", function () {
|
140 |
+
|
141 |
+
// This request was already sent, clear it up!
|
142 |
+
if ("number" === typeof (timer))
|
143 |
+
{
|
144 |
+
clearInterval(timer);
|
145 |
+
}
|
146 |
+
|
147 |
+
var cloneID = this.value;
|
148 |
+
|
149 |
+
timer = setTimeout(
|
150 |
+
function () {
|
151 |
+
ajax(
|
152 |
+
{
|
153 |
+
action: "wpstg_check_clone",
|
154 |
+
cloneID: cloneID
|
155 |
+
},
|
156 |
+
function (response)
|
157 |
+
{
|
158 |
+
if (response.status === "success")
|
159 |
+
{
|
160 |
+
cache.get("#wpstg-new-clone-id").removeClass("wpstg-error-input");
|
161 |
+
cache.get("#wpstg-start-cloning").removeAttr("disabled");
|
162 |
+
cache.get("#wpstg-clone-id-error").text('').hide();
|
163 |
+
}
|
164 |
+
else
|
165 |
+
{
|
166 |
+
cache.get("#wpstg-new-clone-id").addClass("wpstg-error-input");
|
167 |
+
cache.get("#wpstg-start-cloning").prop("disabled", true);
|
168 |
+
cache.get("#wpstg-clone-id-error").text(response.message).show();
|
169 |
+
}
|
170 |
+
}
|
171 |
+
);
|
172 |
+
},
|
173 |
+
500
|
174 |
+
);
|
175 |
+
})
|
176 |
+
// Restart cloning process
|
177 |
+
.on("click", "#wpstg-start-cloning", function () {
|
178 |
+
that.isCancelled = false;
|
179 |
+
that.getLogs = false;
|
180 |
+
})
|
181 |
+
// Display logs
|
182 |
+
// .on("click", "#wpstg-show-log-button", function (e) {
|
183 |
+
// e.preventDefault();
|
184 |
+
// var $logDetails = cache.get("#wpstg-log-details");
|
185 |
+
//
|
186 |
+
// $logDetails.toggle();
|
187 |
+
//
|
188 |
+
// logscroll();
|
189 |
+
//
|
190 |
+
// that.getLogs = (false === that.getLogs);
|
191 |
+
// });
|
192 |
+
|
193 |
+
cloneActions();
|
194 |
+
};
|
195 |
+
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Clone actions
|
199 |
+
*/
|
200 |
+
var cloneActions = function ()
|
201 |
+
{
|
202 |
+
var $workFlow = cache.get("#wpstg-workflow");
|
203 |
+
|
204 |
+
$workFlow
|
205 |
+
// Cancel cloning
|
206 |
+
.on("click", "#wpstg-cancel-cloning", function () {
|
207 |
+
if (!confirm("Are you sure you want to cancel cloning process?"))
|
208 |
+
{
|
209 |
+
return false;
|
210 |
+
}
|
211 |
+
|
212 |
+
var $this = $(this);
|
213 |
+
|
214 |
+
$("#wpstg-try-again, #wpstg-home-link").hide();
|
215 |
+
$this.prop("disabled", true);
|
216 |
+
|
217 |
+
that.isCancelled = true;
|
218 |
+
|
219 |
+
$("#wpstg-cloning-result").text("Please wait...this can take up a while.");
|
220 |
+
$("#wpstg-loader, #wpstg-show-log-button").hide();
|
221 |
+
|
222 |
+
$this.parent().append(ajaxSpinner);
|
223 |
+
|
224 |
+
cancelCloning();
|
225 |
+
})
|
226 |
+
// Cancel update cloning
|
227 |
+
.on("click", "#wpstg-cancel-cloning-update", function () {
|
228 |
+
if (!confirm("Are you sure you want to cancel clone updating process?"))
|
229 |
+
{
|
230 |
+
return false;
|
231 |
+
}
|
232 |
+
|
233 |
+
var $this = $(this);
|
234 |
+
|
235 |
+
$("#wpstg-try-again, #wpstg-home-link").hide();
|
236 |
+
$this.prop("disabled", true);
|
237 |
+
|
238 |
+
that.isCancelled = true;
|
239 |
+
|
240 |
+
$("#wpstg-cloning-result").text("Please wait...this can take up a while.");
|
241 |
+
$("#wpstg-loader, #wpstg-show-log-button").hide();
|
242 |
+
|
243 |
+
$this.parent().append(ajaxSpinner);
|
244 |
+
|
245 |
+
cancelCloningUpdate();
|
246 |
+
})
|
247 |
+
// Delete clone - confirmation
|
248 |
+
.on("click", ".wpstg-remove-clone[data-clone]", function (e) {
|
249 |
+
e.preventDefault();
|
250 |
+
|
251 |
+
var $existingClones = cache.get("#wpstg-existing-clones");
|
252 |
+
|
253 |
+
$workFlow.removeClass('active');
|
254 |
+
|
255 |
+
cache.get("#wpstg-loader").show();
|
256 |
+
|
257 |
+
ajax(
|
258 |
+
{
|
259 |
+
action: "wpstg_confirm_delete_clone",
|
260 |
+
nonce: wpstg.nonce,
|
261 |
+
clone: $(this).data("clone")
|
262 |
+
},
|
263 |
+
function (response)
|
264 |
+
{
|
265 |
+
cache.get("#wpstg-removing-clone").html(response);
|
266 |
+
|
267 |
+
$existingClones.children("img").remove();
|
268 |
+
|
269 |
+
cache.get("#wpstg-loader").hide();
|
270 |
+
},
|
271 |
+
"HTML"
|
272 |
+
);
|
273 |
+
})
|
274 |
+
// Delete clone - confirmed
|
275 |
+
.on("click", "#wpstg-remove-clone", function (e) {
|
276 |
+
e.preventDefault();
|
277 |
+
|
278 |
+
cache.get("#wpstg-removing-clone").addClass("loading");
|
279 |
+
|
280 |
+
cache.get("#wpstg-loader").show();
|
281 |
+
|
282 |
+
deleteClone($(this).data("clone"));
|
283 |
+
})
|
284 |
+
// Cancel deleting clone
|
285 |
+
.on("click", "#wpstg-cancel-removing", function (e) {
|
286 |
+
e.preventDefault();
|
287 |
+
$(".wpstg-clone").removeClass("active");
|
288 |
+
cache.get("#wpstg-removing-clone").html('');
|
289 |
+
})
|
290 |
+
// Update
|
291 |
+
.on("click", ".wpstg-execute-clone", function (e) {
|
292 |
+
e.preventDefault();
|
293 |
+
|
294 |
+
if (!confirm("Are you sure you want to update the staging site? All your staging site modifications will be overwritten with the data from the live site. So make sure that your live site is up to date."))
|
295 |
+
{
|
296 |
+
return false;
|
297 |
+
}
|
298 |
+
|
299 |
+
var clone = $(this).data("clone");
|
300 |
+
|
301 |
+
$workFlow.addClass("loading");
|
302 |
+
|
303 |
+
ajax(
|
304 |
+
{
|
305 |
+
action: "wpstg_scanning",
|
306 |
+
clone: clone,
|
307 |
+
nonce: wpstg.nonce
|
308 |
+
},
|
309 |
+
function (response)
|
310 |
+
{
|
311 |
+
if (response.length < 1)
|
312 |
+
{
|
313 |
+
showError("Something went wrong, please try again");
|
314 |
+
}
|
315 |
+
|
316 |
+
$workFlow.removeClass("loading").html(response);
|
317 |
+
|
318 |
+
cache.get(".wpstg-current-step")
|
319 |
+
.removeClass("wpstg-current-step")
|
320 |
+
.next("li")
|
321 |
+
.addClass("wpstg-current-step");
|
322 |
+
},
|
323 |
+
"HTML"
|
324 |
+
);
|
325 |
+
});
|
326 |
+
};
|
327 |
+
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Ajax Requests
|
331 |
+
* @param {Object} data
|
332 |
+
* @param {Function} callback
|
333 |
+
* @param {String} dataType
|
334 |
+
* @param {Boolean} showErrors
|
335 |
+
*/
|
336 |
+
var ajax = function (data, callback, dataType, showErrors)
|
337 |
+
{
|
338 |
+
if ("undefined" === typeof (dataType))
|
339 |
+
{
|
340 |
+
dataType = "json";
|
341 |
+
}
|
342 |
+
|
343 |
+
if (false !== showErrors)
|
344 |
+
{
|
345 |
+
showErrors = true;
|
346 |
+
}
|
347 |
+
|
348 |
+
$.ajax({
|
349 |
+
url: ajaxurl,
|
350 |
+
type: "POST",
|
351 |
+
dataType: dataType,
|
352 |
+
cache: false,
|
353 |
+
data: data,
|
354 |
+
error: function (xhr, textStatus, errorThrown) {
|
355 |
+
console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
|
356 |
+
console.log(textStatus);
|
357 |
+
|
358 |
+
if (false === showErrors)
|
359 |
+
{
|
360 |
+
return false;
|
361 |
+
}
|
362 |
+
|
363 |
+
|
364 |
+
showError(
|
365 |
+
"Fatal Unknown Error. Go to WP Staging > Settings and lower 'File Copy Limit' and DB query limit" +
|
366 |
+
"Than try again. If this does not help, " +
|
367 |
+
"<a href='https://wpquads.com/support/' target='_blank'>open a support ticket</a> "
|
368 |
+
);
|
369 |
+
},
|
370 |
+
success: function (data) {
|
371 |
+
if ("function" === typeof (callback))
|
372 |
+
{
|
373 |
+
callback(data);
|
374 |
+
}
|
375 |
+
},
|
376 |
+
statusCode: {
|
377 |
+
404: function (data) {
|
378 |
+
showError("Something went wrong; can't find ajax request URL!");
|
379 |
+
},
|
380 |
+
500: function () {
|
381 |
+
showError("Something went wrong; internal server error while processing the request!");
|
382 |
+
}
|
383 |
+
}
|
384 |
+
});
|
385 |
+
};
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Next / Previous Step Clicks to Navigate Through Staging Job
|
389 |
+
*/
|
390 |
+
var stepButtons = function ()
|
391 |
+
{
|
392 |
+
var $workFlow = cache.get("#wpstg-workflow");
|
393 |
+
|
394 |
+
$workFlow
|
395 |
+
// Next Button
|
396 |
+
.on("click", ".wpstg-next-step-link", function (e) {
|
397 |
+
e.preventDefault();
|
398 |
+
|
399 |
+
var $this = $(this),
|
400 |
+
isScan = false;
|
401 |
+
|
402 |
+
// Button is disabled
|
403 |
+
if ($this.attr("disabled"))
|
404 |
+
{
|
405 |
+
return false;
|
406 |
+
}
|
407 |
+
|
408 |
+
// Add loading overlay
|
409 |
+
$workFlow.addClass("loading");
|
410 |
+
|
411 |
+
// Prepare data
|
412 |
+
that.data = {
|
413 |
+
action: $this.data("action"),
|
414 |
+
nonce: wpstg.nonce
|
415 |
+
};
|
416 |
+
|
417 |
+
// Cloning data
|
418 |
+
getCloningData();
|
419 |
+
|
420 |
+
console.log(that.data);
|
421 |
+
|
422 |
+
isScan = ("wpstg_scanning" === that.action);
|
423 |
+
|
424 |
+
// Send ajax request
|
425 |
+
ajax(
|
426 |
+
that.data,
|
427 |
+
function (response) {
|
428 |
+
|
429 |
+
if (response.length < 1)
|
430 |
+
{
|
431 |
+
showError("Something went wrong, please try again");
|
432 |
+
}
|
433 |
+
|
434 |
+
// Styling of elements
|
435 |
+
$workFlow.removeClass("loading").html(response);
|
436 |
+
|
437 |
+
cache.get(".wpstg-current-step")
|
438 |
+
.removeClass("wpstg-current-step")
|
439 |
+
.next("li")
|
440 |
+
.addClass("wpstg-current-step");
|
441 |
+
|
442 |
+
// Start cloning
|
443 |
+
that.startCloning();
|
444 |
+
//processing();
|
445 |
+
},
|
446 |
+
"HTML"
|
447 |
+
);
|
448 |
+
})
|
449 |
+
// Previous Button
|
450 |
+
.on("click", ".wpstg-prev-step-link", function (e) {
|
451 |
+
e.preventDefault();
|
452 |
+
cache.get("#wpstg-loader").removeClass('wpstg-finished');
|
453 |
+
cache.get("#wpstg-loader").hide();
|
454 |
+
loadOverview();
|
455 |
+
});
|
456 |
+
};
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Get Included (Checked) Database Tables
|
460 |
+
* @returns {Array}
|
461 |
+
*/
|
462 |
+
var getIncludedTables = function ()
|
463 |
+
{
|
464 |
+
var includedTables = [];
|
465 |
+
|
466 |
+
$(".wpstg-db-table input:checked").each(function () {
|
467 |
+
includedTables.push(this.name);
|
468 |
+
});
|
469 |
+
|
470 |
+
return includedTables;
|
471 |
+
};
|
472 |
+
/**
|
473 |
+
* Get Excluded (Unchecked) Database Tables
|
474 |
+
* @returns {Array}
|
475 |
+
*/
|
476 |
+
var getExcludedTables = function ()
|
477 |
+
{
|
478 |
+
var excludedTables = [];
|
479 |
+
|
480 |
+
$(".wpstg-db-table input:not(:checked)").each(function () {
|
481 |
+
excludedTables.push(this.name);
|
482 |
+
});
|
483 |
+
|
484 |
+
return excludedTables;
|
485 |
+
};
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Get Included Directories
|
489 |
+
* @returns {Array}
|
490 |
+
*/
|
491 |
+
var getIncludedDirectories = function ()
|
492 |
+
{
|
493 |
+
var includedDirectories = [];
|
494 |
+
|
495 |
+
$(".wpstg-dir input:checked").each(function () {
|
496 |
+
var $this = $(this);
|
497 |
+
if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
498 |
+
{
|
499 |
+
includedDirectories.push($this.val());
|
500 |
+
}
|
501 |
+
});
|
502 |
+
|
503 |
+
return includedDirectories;
|
504 |
+
};
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Get Excluded Directories
|
508 |
+
* @returns {Array}
|
509 |
+
*/
|
510 |
+
var getExcludedDirectories = function ()
|
511 |
+
{
|
512 |
+
var excludedDirectories = [];
|
513 |
+
|
514 |
+
$(".wpstg-dir input:not(:checked)").each(function () {
|
515 |
+
var $this = $(this);
|
516 |
+
if (!$this.parent(".wpstg-dir").parents(".wpstg-dir").children(".wpstg-expand-dirs").hasClass("disabled"))
|
517 |
+
{
|
518 |
+
excludedDirectories.push($this.val());
|
519 |
+
}
|
520 |
+
});
|
521 |
+
|
522 |
+
return excludedDirectories;
|
523 |
+
};
|
524 |
+
|
525 |
+
/**
|
526 |
+
* Get Included Extra Directories
|
527 |
+
* @returns {Array}
|
528 |
+
*/
|
529 |
+
var getIncludedExtraDirectories = function ()
|
530 |
+
{
|
531 |
+
var extraDirectories = [];
|
532 |
+
|
533 |
+
if (!$("#wpstg_extraDirectories").val()) {
|
534 |
+
return extraDirectories;
|
535 |
+
}
|
536 |
+
|
537 |
+
var extraDirectories = $("#wpstg_extraDirectories").val().split(/\r?\n/);
|
538 |
+
console.log(extraDirectories);
|
539 |
+
|
540 |
+
//excludedDirectories.push($this.val());
|
541 |
+
|
542 |
+
return extraDirectories;
|
543 |
+
};
|
544 |
+
|
545 |
+
|
546 |
+
|
547 |
+
/**
|
548 |
+
* Get Cloning Step Data
|
549 |
+
*/
|
550 |
+
var getCloningData = function ()
|
551 |
+
{
|
552 |
+
if ("wpstg_cloning" !== that.data.action && "wpstg_update" !== that.data.action)
|
553 |
+
{
|
554 |
+
return;
|
555 |
+
}
|
556 |
+
|
557 |
+
that.data.cloneID = $("#wpstg-new-clone-id").val() || new Date().getTime().toString();
|
558 |
+
// Remove this to keep &_POST[] small otherwise mod_security will throw error 404
|
559 |
+
//that.data.excludedTables = getExcludedTables();
|
560 |
+
that.data.includedTables = getIncludedTables();
|
561 |
+
that.data.includedDirectories = getIncludedDirectories();
|
562 |
+
that.data.excludedDirectories = getExcludedDirectories();
|
563 |
+
that.data.extraDirectories = getIncludedExtraDirectories();
|
564 |
+
console.log(that.data);
|
565 |
+
|
566 |
+
};
|
567 |
+
|
568 |
+
/**
|
569 |
+
* Loads Overview (first step) of Staging Job
|
570 |
+
*/
|
571 |
+
var loadOverview = function ()
|
572 |
+
{
|
573 |
+
var $workFlow = cache.get("#wpstg-workflow");
|
574 |
+
|
575 |
+
$workFlow.addClass("loading");
|
576 |
+
|
577 |
+
ajax(
|
578 |
+
{
|
579 |
+
action: "wpstg_overview",
|
580 |
+
nonce: wpstg.nonce
|
581 |
+
},
|
582 |
+
function (response) {
|
583 |
+
|
584 |
+
if (response.length < 1)
|
585 |
+
{
|
586 |
+
showError("Something went wrong, please try again");
|
587 |
+
}
|
588 |
+
|
589 |
+
var $currentStep = cache.get(".wpstg-current-step");
|
590 |
+
|
591 |
+
// Styling of elements
|
592 |
+
$workFlow.removeClass("loading").html(response);
|
593 |
+
|
594 |
+
},
|
595 |
+
"HTML"
|
596 |
+
);
|
597 |
+
};
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Load Tabs
|
601 |
+
*/
|
602 |
+
var tabs = function ()
|
603 |
+
{
|
604 |
+
// var $loaded = false;
|
605 |
+
//
|
606 |
+
// if ($loaded === false) {
|
607 |
+
// console.log('select default tables');
|
608 |
+
//
|
609 |
+
// $(".wpstg-db-table input").each(function () {
|
610 |
+
//
|
611 |
+
// $loaded = true;
|
612 |
+
//
|
613 |
+
// if ($(this).attr('name').match("^" + wpstg.tblprefix)) {
|
614 |
+
// $(this).prop("checked", true);
|
615 |
+
// } else {
|
616 |
+
// $(this).prop("checked", false);
|
617 |
+
// }
|
618 |
+
// });
|
619 |
+
// }
|
620 |
+
|
621 |
+
cache.get("#wpstg-workflow").on("click", ".wpstg-tab-header", function (e) {
|
622 |
+
e.preventDefault();
|
623 |
+
|
624 |
+
var $this = $(this);
|
625 |
+
var $section = cache.get($this.data("id"));
|
626 |
+
|
627 |
+
$this.toggleClass("expand");
|
628 |
+
|
629 |
+
$section.slideToggle();
|
630 |
+
|
631 |
+
if ($this.hasClass("expand"))
|
632 |
+
{
|
633 |
+
$this.find(".wpstg-tab-triangle").html("▼");
|
634 |
+
}
|
635 |
+
else
|
636 |
+
{
|
637 |
+
$this.find(".wpstg-tab-triangle").html("►");
|
638 |
+
}
|
639 |
+
|
640 |
+
|
641 |
+
|
642 |
+
});
|
643 |
+
};
|
644 |
+
|
645 |
+
/**
|
646 |
+
* Delete Clone
|
647 |
+
* @param {String} clone
|
648 |
+
*/
|
649 |
+
var deleteClone = function (clone)
|
650 |
+
{
|
651 |
+
|
652 |
+
ajax(
|
653 |
+
{
|
654 |
+
action: "wpstg_delete_clone",
|
655 |
+
clone: clone,
|
656 |
+
nonce: wpstg.nonce,
|
657 |
+
excludedTables: getExcludedTables(),
|
658 |
+
deleteDir: $("#deleteDirectory:checked").val()
|
659 |
+
},
|
660 |
+
function (response)
|
661 |
+
{
|
662 |
+
if (response) {
|
663 |
+
// Error
|
664 |
+
if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
|
665 |
+
showError(response.message);
|
666 |
+
console.log(response.message);
|
667 |
+
}
|
668 |
+
|
669 |
+
// Finished
|
670 |
+
if ("undefined" !== typeof response.delete && response.delete === 'finished') {
|
671 |
+
|
672 |
+
cache.get("#wpstg-removing-clone").removeClass("loading").html('');
|
673 |
+
$(".wpstg-clone#" + clone).remove();
|
674 |
+
|
675 |
+
if ($(".wpstg-clone").length < 1)
|
676 |
+
{
|
677 |
+
cache.get("#wpstg-existing-clones").find("h3").text('');
|
678 |
+
}
|
679 |
+
|
680 |
+
cache.get("#wpstg-loader").hide();
|
681 |
+
return;
|
682 |
+
}
|
683 |
+
}
|
684 |
+
// continue
|
685 |
+
if (true !== response)
|
686 |
+
{
|
687 |
+
deleteClone(clone);
|
688 |
+
return;
|
689 |
+
}
|
690 |
+
|
691 |
+
}
|
692 |
+
);
|
693 |
+
};
|
694 |
+
|
695 |
+
/**
|
696 |
+
* Cancel Cloning Process
|
697 |
+
*/
|
698 |
+
var cancelCloning = function ()
|
699 |
+
{
|
700 |
+
if (true === that.isFinished)
|
701 |
+
{
|
702 |
+
return true;
|
703 |
+
}
|
704 |
+
|
705 |
+
ajax(
|
706 |
+
{
|
707 |
+
action: "wpstg_cancel_clone",
|
708 |
+
clone: that.data.cloneID,
|
709 |
+
nonce: wpstg.nonce
|
710 |
+
},
|
711 |
+
function (response)
|
712 |
+
{
|
713 |
+
|
714 |
+
|
715 |
+
if (response && "undefined" !== typeof (response.delete) && response.delete === "finished") {
|
716 |
+
// Load overview
|
717 |
+
loadOverview();
|
718 |
+
return;
|
719 |
+
}
|
720 |
+
|
721 |
+
if (true !== response)
|
722 |
+
{
|
723 |
+
// continue
|
724 |
+
cancelCloning();
|
725 |
+
return;
|
726 |
+
}
|
727 |
+
|
728 |
+
// Load overview
|
729 |
+
loadOverview();
|
730 |
+
}
|
731 |
+
);
|
732 |
+
};
|
733 |
+
/**
|
734 |
+
* Cancel Cloning Process
|
735 |
+
*/
|
736 |
+
var cancelCloningUpdate = function ()
|
737 |
+
{
|
738 |
+
if (true === that.isFinished)
|
739 |
+
{
|
740 |
+
return true;
|
741 |
+
}
|
742 |
+
|
743 |
+
//alert(that.data.cloneID);
|
744 |
+
ajax(
|
745 |
+
{
|
746 |
+
action: "wpstg_cancel_update",
|
747 |
+
clone: that.data.cloneID,
|
748 |
+
nonce: wpstg.nonce
|
749 |
+
},
|
750 |
+
function (response)
|
751 |
+
{
|
752 |
+
|
753 |
+
|
754 |
+
if (response && "undefined" !== typeof (response.delete) && response.delete === "finished") {
|
755 |
+
// Load overview
|
756 |
+
loadOverview();
|
757 |
+
return;
|
758 |
+
}
|
759 |
+
|
760 |
+
if (true !== response)
|
761 |
+
{
|
762 |
+
// continue
|
763 |
+
cancelCloningUpdate();
|
764 |
+
return;
|
765 |
+
}
|
766 |
+
|
767 |
+
// Load overview
|
768 |
+
loadOverview();
|
769 |
+
}
|
770 |
+
);
|
771 |
+
};
|
772 |
+
|
773 |
+
/**
|
774 |
+
* Scroll the window log to bottom
|
775 |
+
* @returns void
|
776 |
+
*/
|
777 |
+
var logscroll = function () {
|
778 |
+
var $div = cache.get("#wpstg-log-details");
|
779 |
+
if ("undefined" !== typeof ($div[0])) {
|
780 |
+
$div.scrollTop($div[0].scrollHeight);
|
781 |
+
}
|
782 |
+
}
|
783 |
+
|
784 |
+
/**
|
785 |
+
* Append the log to the logging window
|
786 |
+
* @param string log
|
787 |
+
* @returns void
|
788 |
+
*/
|
789 |
+
var getLogs = function (log)
|
790 |
+
{
|
791 |
+
if (log != null && "undefined" !== typeof (log)) {
|
792 |
+
if (log.constructor === Array) {
|
793 |
+
$.each(log, function (index, value) {
|
794 |
+
if (value === null) {
|
795 |
+
return;
|
796 |
+
}
|
797 |
+
if (value.type === 'ERROR') {
|
798 |
+
cache.get("#wpstg-log-details").append('<span style="color:red;">[' + value.type + ']</span>-' + '[' + value.date + '] ' + value.message + '</br>');
|
799 |
+
} else {
|
800 |
+
cache.get("#wpstg-log-details").append('[' + value.type + ']-' + '[' + value.date + '] ' + value.message + '</br>');
|
801 |
+
}
|
802 |
+
})
|
803 |
+
} else {
|
804 |
+
cache.get("#wpstg-log-details").append('[' + log.type + ']-' + '[' + log.date + '] ' + log.message + '</br>');
|
805 |
+
}
|
806 |
+
}
|
807 |
+
logscroll();
|
808 |
+
|
809 |
+
};
|
810 |
+
|
811 |
+
/**
|
812 |
+
* Check diskspace
|
813 |
+
* @returns string json
|
814 |
+
*/
|
815 |
+
var checkDiskSpace = function () {
|
816 |
+
cache.get("#wpstg-check-space").on("click", function (e) {
|
817 |
+
cache.get("#wpstg-loader").show();
|
818 |
+
console.log("check disk space");
|
819 |
+
ajax(
|
820 |
+
{
|
821 |
+
action: "wpstg_check_disk_space",
|
822 |
+
nonce: wpstg.nonce
|
823 |
+
},
|
824 |
+
function (response)
|
825 |
+
{
|
826 |
+
if (false === response)
|
827 |
+
{
|
828 |
+
cache.get("#wpstg-clone-id-error").text('Can not detect disk space').show();
|
829 |
+
cache.get("#wpstg-loader").hide();
|
830 |
+
return;
|
831 |
+
}
|
832 |
+
|
833 |
+
// Not enough disk space
|
834 |
+
cache.get("#wpstg-clone-id-error").text('Available free disk space ' + response.freespace + ' | Estimated necessary disk space: ' + response.usedspace).show();
|
835 |
+
cache.get("#wpstg-loader").hide();
|
836 |
+
},
|
837 |
+
"json",
|
838 |
+
false
|
839 |
+
);
|
840 |
+
});
|
841 |
+
|
842 |
+
}
|
843 |
+
|
844 |
+
|
845 |
+
|
846 |
+
/**
|
847 |
+
* Start Cloning Process
|
848 |
+
* @type {Function}
|
849 |
+
*/
|
850 |
+
that.startCloning = (function () {
|
851 |
+
|
852 |
+
// Register function for checking disk space
|
853 |
+
checkDiskSpace();
|
854 |
+
|
855 |
+
if ("wpstg_cloning" !== that.data.action && "wpstg_update" !== that.data.action)
|
856 |
+
{
|
857 |
+
return;
|
858 |
+
}
|
859 |
+
|
860 |
+
// Start the process
|
861 |
+
start();
|
862 |
+
|
863 |
+
// Functions
|
864 |
+
// Start
|
865 |
+
function start()
|
866 |
+
{
|
867 |
+
console.log("Starting cloning process...");
|
868 |
+
|
869 |
+
cache.get("#wpstg-loader").show();
|
870 |
+
|
871 |
+
// Clone Database
|
872 |
+
setTimeout(function () {
|
873 |
+
cloneDatabase();
|
874 |
+
}, wpstg.cpuLoad);
|
875 |
+
}
|
876 |
+
|
877 |
+
// Step 1: Clone Database
|
878 |
+
function cloneDatabase()
|
879 |
+
{
|
880 |
+
if (true === that.isCancelled)
|
881 |
+
{
|
882 |
+
return false;
|
883 |
+
}
|
884 |
+
|
885 |
+
if (true === that.getLogs)
|
886 |
+
{
|
887 |
+
getLogs();
|
888 |
+
}
|
889 |
+
|
890 |
+
setTimeout(
|
891 |
+
function () {
|
892 |
+
ajax(
|
893 |
+
{
|
894 |
+
action: "wpstg_clone_database",
|
895 |
+
nonce: wpstg.nonce
|
896 |
+
},
|
897 |
+
function (response) {
|
898 |
+
// Add percentage
|
899 |
+
if ("undefined" !== typeof (response.percentage))
|
900 |
+
{
|
901 |
+
cache.get("#wpstg-db-progress").width(response.percentage + '%');
|
902 |
+
}
|
903 |
+
// Add Log
|
904 |
+
if ("undefined" !== typeof (response.last_msg))
|
905 |
+
{
|
906 |
+
getLogs(response.last_msg);
|
907 |
+
}
|
908 |
+
|
909 |
+
// Continue clone DB
|
910 |
+
if (false === response.status)
|
911 |
+
{
|
912 |
+
setTimeout(function () {
|
913 |
+
cloneDatabase();
|
914 |
+
}, wpstg.cpuLoad);
|
915 |
+
}
|
916 |
+
// Next Step
|
917 |
+
else if (true === response.status)
|
918 |
+
{
|
919 |
+
//console.log('prepareDirectories ' + response.status);
|
920 |
+
setTimeout(function () {
|
921 |
+
prepareDirectories();
|
922 |
+
}, wpstg.cpuLoad);
|
923 |
+
}
|
924 |
+
}
|
925 |
+
);
|
926 |
+
},
|
927 |
+
500
|
928 |
+
);
|
929 |
+
}
|
930 |
+
|
931 |
+
// Step 2: Prepare Directories
|
932 |
+
function prepareDirectories()
|
933 |
+
{
|
934 |
+
if (true === that.isCancelled)
|
935 |
+
{
|
936 |
+
return false;
|
937 |
+
}
|
938 |
+
|
939 |
+
if (true === that.getLogs)
|
940 |
+
{
|
941 |
+
getLogs();
|
942 |
+
}
|
943 |
+
|
944 |
+
setTimeout(
|
945 |
+
function () {
|
946 |
+
ajax(
|
947 |
+
{
|
948 |
+
action: "wpstg_clone_prepare_directories",
|
949 |
+
nonce: wpstg.nonce
|
950 |
+
},
|
951 |
+
function (response) {
|
952 |
+
|
953 |
+
// Error
|
954 |
+
if ("undefined" !== typeof response.error && "undefined" !== typeof response.message) {
|
955 |
+
showError(response.message);
|
956 |
+
console.log(response.message);
|
957 |
+
}
|
958 |
+
|
959 |
+
// Add percentage
|
960 |
+
if ("undefined" !== typeof (response.percentage))
|
961 |
+
{
|
962 |
+
cache.get("#wpstg-directories-progress").width(response.percentage + '%');
|
963 |
+
}
|
964 |
+
|
965 |
+
// Add Log
|
966 |
+
if ("undefined" !== typeof (response.last_msg))
|
967 |
+
{
|
968 |
+
getLogs(response.last_msg);
|
969 |
+
}
|
970 |
+
|
971 |
+
if (false === response.status)
|
972 |
+
{
|
973 |
+
setTimeout(function () {
|
974 |
+
prepareDirectories();
|
975 |
+
}, wpstg.cpuLoad);
|
976 |
+
}
|
977 |
+
else if (true === response.status)
|
978 |
+
{
|
979 |
+
console.log('prepareDirectories' + response.status);
|
980 |
+
cloneFiles();
|
981 |
+
}
|
982 |
+
}
|
983 |
+
);
|
984 |
+
},
|
985 |
+
500
|
986 |
+
);
|
987 |
+
}
|
988 |
+
|
989 |
+
// Step 3: Clone Files
|
990 |
+
function cloneFiles()
|
991 |
+
{
|
992 |
+
if (true === that.isCancelled)
|
993 |
+
{
|
994 |
+
return false;
|
995 |
+
}
|
996 |
+
|
997 |
+
if (true === that.getLogs)
|
998 |
+
{
|
999 |
+
getLogs();
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
ajax(
|
1003 |
+
{
|
1004 |
+
action: "wpstg_clone_files",
|
1005 |
+
nonce: wpstg.nonce
|
1006 |
+
},
|
1007 |
+
function (response) {
|
1008 |
+
// Add percentage
|
1009 |
+
if ("undefined" !== typeof (response.percentage))
|
1010 |
+
{
|
1011 |
+
cache.get("#wpstg-files-progress").width(response.percentage + '%');
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
// Add Log
|
1015 |
+
if ("undefined" !== typeof (response.last_msg))
|
1016 |
+
{
|
1017 |
+
getLogs(response.last_msg);
|
1018 |
+
}
|
1019 |
+
|
1020 |
+
if (false === response.status)
|
1021 |
+
{
|
1022 |
+
setTimeout(function () {
|
1023 |
+
cloneFiles();
|
1024 |
+
}, wpstg.cpuLoad);
|
1025 |
+
}
|
1026 |
+
else if (true === response.status)
|
1027 |
+
{
|
1028 |
+
setTimeout(function () {
|
1029 |
+
replaceData();
|
1030 |
+
}, wpstg.cpuLoad);
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
+
);
|
1034 |
+
}
|
1035 |
+
|
1036 |
+
// Step 4: Replace Data
|
1037 |
+
function replaceData()
|
1038 |
+
{
|
1039 |
+
if (true === that.isCancelled)
|
1040 |
+
{
|
1041 |
+
return false;
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
if (true === that.getLogs)
|
1045 |
+
{
|
1046 |
+
console.log('getLogs1')
|
1047 |
+
getLogs();
|
1048 |
+
}
|
1049 |
+
|
1050 |
+
ajax(
|
1051 |
+
{
|
1052 |
+
action: "wpstg_clone_replace_data",
|
1053 |
+
nonce: wpstg.nonce
|
1054 |
+
},
|
1055 |
+
function (response) {
|
1056 |
+
// Add percentage
|
1057 |
+
if ("undefined" !== typeof (response.percentage))
|
1058 |
+
{
|
1059 |
+
cache.get("#wpstg-links-progress").width(response.percentage + '%');
|
1060 |
+
}
|
1061 |
+
|
1062 |
+
// Add Log
|
1063 |
+
if ("undefined" !== typeof (response.last_msg))
|
1064 |
+
{
|
1065 |
+
console.log('get Logs');
|
1066 |
+
getLogs(response.last_msg);
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
if (false === response.status)
|
1070 |
+
{
|
1071 |
+
setTimeout(function () {
|
1072 |
+
console.log('replace data');
|
1073 |
+
replaceData();
|
1074 |
+
}, wpstg.cpuLoad);
|
1075 |
+
}
|
1076 |
+
else if (true === response.status)
|
1077 |
+
{
|
1078 |
+
console.log('finish');
|
1079 |
+
finish();
|
1080 |
+
}
|
1081 |
+
}
|
1082 |
+
);
|
1083 |
+
}
|
1084 |
+
|
1085 |
+
// Finish
|
1086 |
+
function finish()
|
1087 |
+
{
|
1088 |
+
if (true === that.getLogs)
|
1089 |
+
{
|
1090 |
+
getLogs();
|
1091 |
+
}
|
1092 |
+
|
1093 |
+
if (true === that.isCancelled || true === that.isFinished)
|
1094 |
+
{
|
1095 |
+
cache.get("#wpstg-loader").hide();
|
1096 |
+
return false;
|
1097 |
+
}
|
1098 |
+
|
1099 |
+
ajax(
|
1100 |
+
{
|
1101 |
+
action: "wpstg_clone_finish",
|
1102 |
+
nonce: wpstg.nonce
|
1103 |
+
},
|
1104 |
+
function (response)
|
1105 |
+
{
|
1106 |
+
// Invalid response
|
1107 |
+
if ("object" !== typeof (response))
|
1108 |
+
{
|
1109 |
+
showError(
|
1110 |
+
"Couldn't finish the cloning process properly. " +
|
1111 |
+
"Your clone has been copied but failed to do clean up and " +
|
1112 |
+
"saving its records to the database." +
|
1113 |
+
"Please contact support and provide your logs."
|
1114 |
+
);
|
1115 |
+
|
1116 |
+
return;
|
1117 |
+
}
|
1118 |
+
|
1119 |
+
// Add Log
|
1120 |
+
if ("undefined" !== typeof (response.last_msg))
|
1121 |
+
{
|
1122 |
+
getLogs(response.last_msg);
|
1123 |
+
}
|
1124 |
+
|
1125 |
+
console.log("Cloning process finished");
|
1126 |
+
|
1127 |
+
var $link1 = cache.get("#wpstg-clone-url-1");
|
1128 |
+
var $link = cache.get("#wpstg-clone-url");
|
1129 |
+
|
1130 |
+
cache.get("#wpstg_staging_name").html(that.data.cloneID);
|
1131 |
+
cache.get("#wpstg-finished-result").show();
|
1132 |
+
cache.get("#wpstg-cancel-cloning").prop("disabled", true);
|
1133 |
+
cache.get("#wpstg-cancel-cloning-update").prop("disabled", true);
|
1134 |
+
// $link1.attr("href", $link1.attr("href") + '/' + response.directoryName);
|
1135 |
+
// $link1.append('/' + response.directoryName);
|
1136 |
+
// $link.attr("href", $link.attr("href") + '/' + response.directoryName);
|
1137 |
+
$link1.attr("href", response.url);
|
1138 |
+
$link.attr("href", response.url);
|
1139 |
+
cache.get("#wpstg-remove-clone").data("clone", that.data.cloneID);
|
1140 |
+
|
1141 |
+
// Finished
|
1142 |
+
that.isFinished = true;
|
1143 |
+
|
1144 |
+
finish();
|
1145 |
+
}
|
1146 |
+
);
|
1147 |
+
}
|
1148 |
+
});
|
1149 |
+
|
1150 |
+
|
1151 |
+
/**
|
1152 |
+
* Initiation
|
1153 |
+
* @type {Function}
|
1154 |
+
*/
|
1155 |
+
that.init = (function () {
|
1156 |
+
loadOverview();
|
1157 |
+
elements();
|
1158 |
+
//startUpdate();
|
1159 |
+
stepButtons();
|
1160 |
+
tabs();
|
1161 |
+
//optimizer();
|
1162 |
+
});
|
1163 |
+
|
1164 |
+
/**
|
1165 |
+
* Ajax call
|
1166 |
+
* @type {ajax}
|
1167 |
+
*/
|
1168 |
+
that.ajax = ajax;
|
1169 |
+
that.showError = showError;
|
1170 |
+
that.getLogs = getLogs;
|
1171 |
+
that.loadOverview = loadOverview;
|
1172 |
+
|
1173 |
+
return that;
|
1174 |
+
})(jQuery);
|
1175 |
+
|
1176 |
+
jQuery(document).ready(function () {
|
1177 |
+
WPStaging.init();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1178 |
});
|
apps/Backend/views/_includes/messages/beta.php
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
-
<div class="wpstg_beta_notice error" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
-
<p>
|
3 |
-
WP Staging is well tested and we did a lot to catch every possible error but
|
4 |
-
we can not handle all possible combinations of server, plugins and themes. <br>
|
5 |
-
<strong>BEFORE</strong> you create your first staging site it´s highly recommended
|
6 |
-
<strong>to make a full backup of your website</strong> first!
|
7 |
-
</p>
|
8 |
-
<p>
|
9 |
-
A good plugin for an entire WordPress backup is the free one
|
10 |
-
<a href="https://wordpress.org/plugins/backwpup/" target="_blank">BackWPup</a>
|
11 |
-
</p>
|
12 |
-
<ul>
|
13 |
-
<li>
|
14 |
-
<a href="javascript:void(0);" class="wpstg_hide_beta" title="I understand" data-url="<?php echo admin_url("admin-ajax.php")?>" style="font-weight:bold;color:#00a0d2;">
|
15 |
-
I understand! (Do not show this again)
|
16 |
-
</a>
|
17 |
-
</li>
|
18 |
-
</ul>
|
19 |
-
</div>
|
20 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-beta.js"?>"></script>
|
1 |
+
<div class="wpstg_beta_notice error" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
+
<p>
|
3 |
+
WP Staging is well tested and we did a lot to catch every possible error but
|
4 |
+
we can not handle all possible combinations of server, plugins and themes. <br>
|
5 |
+
<strong>BEFORE</strong> you create your first staging site it´s highly recommended
|
6 |
+
<strong>to make a full backup of your website</strong> first!
|
7 |
+
</p>
|
8 |
+
<p>
|
9 |
+
A good plugin for an entire WordPress backup is the free one
|
10 |
+
<a href="https://wordpress.org/plugins/backwpup/" target="_blank">BackWPup</a>
|
11 |
+
</p>
|
12 |
+
<ul>
|
13 |
+
<li>
|
14 |
+
<a href="javascript:void(0);" class="wpstg_hide_beta" title="I understand" data-url="<?php echo admin_url("admin-ajax.php")?>" style="font-weight:bold;color:#00a0d2;">
|
15 |
+
I understand! (Do not show this again)
|
16 |
+
</a>
|
17 |
+
</li>
|
18 |
+
</ul>
|
19 |
+
</div>
|
20 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-beta.js"?>"></script>
|
apps/Backend/views/_includes/messages/rating.php
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<div class="wpstg_fivestar updated" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
-
<p>
|
3 |
-
Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.
|
4 |
-
May I ask you to give it a <strong>5-star</strong> rating on Wordpress?
|
5 |
-
<br><br>
|
6 |
-
P.S. Looking for a way to copy plugins and theme files from staging to live site? Try out <a href="https://wp-staging.com" target="_blank">WP Staging Pro</a> <br>
|
7 |
-
</p>
|
8 |
-
|
9 |
-
<p>
|
10 |
-
<strong>Regards,<br>René Hermenau</strong>
|
11 |
-
</p>
|
12 |
-
|
13 |
-
<ul>
|
14 |
-
<li>
|
15 |
-
<a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5#new-post" class="thankyou" target="_new" title="Ok, you deserved it" style="font-weight:bold;">
|
16 |
-
Ok, you deserved it
|
17 |
-
</a>
|
18 |
-
</li>
|
19 |
-
<li>
|
20 |
-
<a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:bold;">
|
21 |
-
I already did
|
22 |
-
</a>
|
23 |
-
</li>
|
24 |
-
<li>
|
25 |
-
<a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:bold;">
|
26 |
-
No, not good enough
|
27 |
-
</a>
|
28 |
-
</li>
|
29 |
-
</ul>
|
30 |
-
</div>
|
31 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-rating.js"?>"></script>
|
1 |
+
<div class="wpstg_fivestar updated" style="box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);">
|
2 |
+
<p>
|
3 |
+
Awesome, you've been using <strong>WP Staging </strong> for more than 1 week.
|
4 |
+
May I ask you to give it a <strong>5-star</strong> rating on Wordpress?
|
5 |
+
<br><br>
|
6 |
+
P.S. Looking for a way to copy plugins and theme files from staging to live site? Try out <a href="https://wp-staging.com" target="_blank">WP Staging Pro</a> <br>
|
7 |
+
</p>
|
8 |
+
|
9 |
+
<p>
|
10 |
+
<strong>Regards,<br>René Hermenau</strong>
|
11 |
+
</p>
|
12 |
+
|
13 |
+
<ul>
|
14 |
+
<li>
|
15 |
+
<a href="https://wordpress.org/support/plugin/wp-staging/reviews/?filter=5#new-post" class="thankyou" target="_new" title="Ok, you deserved it" style="font-weight:bold;">
|
16 |
+
Ok, you deserved it
|
17 |
+
</a>
|
18 |
+
</li>
|
19 |
+
<li>
|
20 |
+
<a href="javascript:void(0);" class="wpstg_hide_rating" title="I already did" style="font-weight:bold;">
|
21 |
+
I already did
|
22 |
+
</a>
|
23 |
+
</li>
|
24 |
+
<li>
|
25 |
+
<a href="javascript:void(0);" class="wpstg_hide_rating" title="No, not good enough" style="font-weight:bold;">
|
26 |
+
No, not good enough
|
27 |
+
</a>
|
28 |
+
</li>
|
29 |
+
</ul>
|
30 |
+
</div>
|
31 |
<script type="text/javascript" src="<?php echo $this->url . "js/wpstg-admin-rating.js"?>"></script>
|
apps/Backend/views/_includes/messages/wp-version-compatible-message.php
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
-
<div class="error">
|
2 |
-
<p>
|
3 |
-
<?php
|
4 |
-
echo sprintf( __(
|
5 |
-
'<strong>Watch out:</strong> This version of WP Staging has not been tested with your WordPress version %2$s.' .
|
6 |
-
'<br/>As WP Staging is using crucial DB and file functions it\'s important that you are using a ' .
|
7 |
-
'WP Staging version <br> which has been verified to be working with your WordPress version. ' .
|
8 |
-
'You risk unexpected data lose if you do not so! ' .
|
9 |
-
'<p><strong>Get the latest WP Staging plugin from <a href="%1$s" target="_blank">https://wp-staging.com</a>.</strong>', 'wpstg'), 'https://wp-staging.com', get_bloginfo( 'version' )
|
10 |
-
);
|
11 |
-
?>
|
12 |
-
</p>
|
13 |
</div>
|
1 |
+
<div class="error">
|
2 |
+
<p>
|
3 |
+
<?php
|
4 |
+
echo sprintf( __(
|
5 |
+
'<strong>Watch out:</strong> This version of WP Staging has not been tested with your WordPress version %2$s.' .
|
6 |
+
'<br/>As WP Staging is using crucial DB and file functions it\'s important that you are using a ' .
|
7 |
+
'WP Staging version <br> which has been verified to be working with your WordPress version. ' .
|
8 |
+
'You risk unexpected data lose if you do not so! ' .
|
9 |
+
'<p><strong>Get the latest WP Staging plugin from <a href="%1$s" target="_blank">https://wp-staging.com</a>.</strong>', 'wpstg'), 'https://wp-staging.com', get_bloginfo( 'version' )
|
10 |
+
);
|
11 |
+
?>
|
12 |
+
</p>
|
13 |
</div>
|
apps/Backend/views/clone/ajax/scan.php
CHANGED
@@ -1,129 +1,129 @@
|
|
1 |
-
<label id="wpstg-clone-label" for="wpstg-new-clone">
|
2 |
-
<?php echo __('Staging Site Name:', 'wpstg')?>
|
3 |
-
<input type="text" id="wpstg-new-clone-id" value="<?php echo $options->current; ?>"<?php if (null !== $options->current) echo " disabled='disabled'"?>>
|
4 |
-
</label>
|
5 |
-
|
6 |
-
<span class="wpstg-error-msg" id="wpstg-clone-id-error" style="display:none;">
|
7 |
-
<?php echo __(
|
8 |
-
"<br>Probably not enough free disk space to create a staging site. ".
|
9 |
-
"<br> You can continue but its likely that the copying process will fail.",
|
10 |
-
"wpstg"
|
11 |
-
)?>
|
12 |
-
</span>
|
13 |
-
|
14 |
-
<div class="wpstg-tabs-wrapper">
|
15 |
-
<a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
|
16 |
-
<span class="wpstg-tab-triangle">►</span>
|
17 |
-
<?php echo __("DB Tables", "wpstg")?>
|
18 |
-
</a>
|
19 |
-
|
20 |
-
<div class="wpstg-tab-section" id="wpstg-scanning-db">
|
21 |
-
<?php do_action("wpstg_scanning_db")?>
|
22 |
-
<h4 style="margin:0">
|
23 |
-
<?php
|
24 |
-
|
25 |
-
echo __(
|
26 |
-
"Uncheck the tables you do not want to copy. Usually you should select tables with prefix '{$scan->prefix}', only.",
|
27 |
-
"wpstg"
|
28 |
-
)?>
|
29 |
-
</h4>
|
30 |
-
<div style="margin-top:10px;margin-bottom:10px;">
|
31 |
-
<a href="#" class="wpstg-button-unselect button"> None </a>
|
32 |
-
<a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\WPStaging::getTablePrefix(), 'wpstg'); ?> </a>
|
33 |
-
</div>
|
34 |
-
<?php
|
35 |
-
//print_r( $options->excludedTables);
|
36 |
-
foreach ($options->tables as $table):
|
37 |
-
$attributes = in_array($table->name, $options->excludedTables) ? '' : "checked";
|
38 |
-
$attributes .= in_array($table->name, $options->clonedTables) ? " disabled" : '';
|
39 |
-
?>
|
40 |
-
<div class="wpstg-db-table">
|
41 |
-
<label>
|
42 |
-
<input class="wpstg-db-table-checkboxes" type="checkbox" name="<?php echo $table->name?>" <?php echo $attributes?>>
|
43 |
-
<?php echo $table->name?>
|
44 |
-
</label>
|
45 |
-
<span class="wpstg-size-info">
|
46 |
-
<?php echo $scan->formatSize($table->size)?>
|
47 |
-
</span>
|
48 |
-
</div>
|
49 |
-
<?php endforeach ?>
|
50 |
-
<div style="margin-top:10px;">
|
51 |
-
<a href="#" class="wpstg-button-unselect button"> None </a>
|
52 |
-
<a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\WPStaging::getTablePrefix(), 'wpstg'); ?> </a>
|
53 |
-
</div>
|
54 |
-
</div>
|
55 |
-
|
56 |
-
<a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
|
57 |
-
<span class="wpstg-tab-triangle">►</span>
|
58 |
-
<?php echo __("Files", "wpstg")?>
|
59 |
-
</a>
|
60 |
-
|
61 |
-
<div class="wpstg-tab-section" id="wpstg-scanning-files">
|
62 |
-
<h4 style="margin:0">
|
63 |
-
<?php echo __("Uncheck the folders you do not want to copy. Click on them for expanding!", "wpstg")?>
|
64 |
-
</h4>
|
65 |
-
|
66 |
-
<?php echo $scan->directoryListing()?>
|
67 |
-
|
68 |
-
<h4 style="margin:10px 0 10px 0">
|
69 |
-
<?php echo __("Extra directories to copy", "wpstg")?>
|
70 |
-
</h4>
|
71 |
-
|
72 |
-
<textarea id="wpstg_extraDirectories" name="wpstg_extraDirectories" style="width:100%;height:250px;"></textarea>
|
73 |
-
<p>
|
74 |
-
<span>
|
75 |
-
<?php
|
76 |
-
echo __(
|
77 |
-
"Enter one folder path per line.<br>".
|
78 |
-
"Folders must start with absolute path: " . $options->root,
|
79 |
-
"wpstg"
|
80 |
-
)
|
81 |
-
?>
|
82 |
-
</span>
|
83 |
-
</p>
|
84 |
-
|
85 |
-
<p>
|
86 |
-
<span>
|
87 |
-
<?php
|
88 |
-
if (isset($options->clone)){
|
89 |
-
echo __("All files will be copied to: ", "wpstg") . $options->root . $options->clone;
|
90 |
-
}
|
91 |
-
?>
|
92 |
-
</span>
|
93 |
-
</p>
|
94 |
-
</div>
|
95 |
-
|
96 |
-
<a href="#" class="wpstg-tab-header" data-id="#wpstg-advanced-settings">
|
97 |
-
<span class="wpstg-tab-triangle">►</span>
|
98 |
-
<?php echo __("Advanced Options", "wpstg")?>
|
99 |
-
</a>
|
100 |
-
|
101 |
-
<div class="wpstg-tab-section" id="wpstg-advanced-settings">
|
102 |
-
Coming Soon...
|
103 |
-
</div>
|
104 |
-
|
105 |
-
</div>
|
106 |
-
|
107 |
-
<button type="button" class="wpstg-prev-step-link wpstg-link-btn button-primary">
|
108 |
-
<?php _e("Back", "wpstg")?>
|
109 |
-
</button>
|
110 |
-
|
111 |
-
<?php
|
112 |
-
if (null !== $options->current)
|
113 |
-
{
|
114 |
-
$label = __("Update Clone", "wpstg");
|
115 |
-
$action = 'wpstg_update';
|
116 |
-
|
117 |
-
echo '<button type="button" id="wpstg-start-updating" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="'.$action.'">'.$label.'</button>';
|
118 |
-
}
|
119 |
-
else
|
120 |
-
{
|
121 |
-
$label = __("Start Cloning", "wpstg");
|
122 |
-
$action = 'wpstg_cloning';
|
123 |
-
|
124 |
-
echo '<button type="button" id="wpstg-start-cloning" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="'.$action.'">'.$label.'</button>';
|
125 |
-
|
126 |
-
}
|
127 |
-
?>
|
128 |
-
|
129 |
<a href="#" id="wpstg-check-space"><?php _e('Check Disk Space', 'wpstg'); ?></a>
|
1 |
+
<label id="wpstg-clone-label" for="wpstg-new-clone">
|
2 |
+
<?php echo __('Staging Site Name:', 'wpstg')?>
|
3 |
+
<input type="text" id="wpstg-new-clone-id" value="<?php echo $options->current; ?>"<?php if (null !== $options->current) echo " disabled='disabled'"?>>
|
4 |
+
</label>
|
5 |
+
|
6 |
+
<span class="wpstg-error-msg" id="wpstg-clone-id-error" style="display:none;">
|
7 |
+
<?php echo __(
|
8 |
+
"<br>Probably not enough free disk space to create a staging site. ".
|
9 |
+
"<br> You can continue but its likely that the copying process will fail.",
|
10 |
+
"wpstg"
|
11 |
+
)?>
|
12 |
+
</span>
|
13 |
+
|
14 |
+
<div class="wpstg-tabs-wrapper">
|
15 |
+
<a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
|
16 |
+
<span class="wpstg-tab-triangle">►</span>
|
17 |
+
<?php echo __("DB Tables", "wpstg")?>
|
18 |
+
</a>
|
19 |
+
|
20 |
+
<div class="wpstg-tab-section" id="wpstg-scanning-db">
|
21 |
+
<?php do_action("wpstg_scanning_db")?>
|
22 |
+
<h4 style="margin:0">
|
23 |
+
<?php
|
24 |
+
|
25 |
+
echo __(
|
26 |
+
"Uncheck the tables you do not want to copy. Usually you should select tables with prefix '{$scan->prefix}', only.",
|
27 |
+
"wpstg"
|
28 |
+
)?>
|
29 |
+
</h4>
|
30 |
+
<div style="margin-top:10px;margin-bottom:10px;">
|
31 |
+
<a href="#" class="wpstg-button-unselect button"> None </a>
|
32 |
+
<a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\WPStaging::getTablePrefix(), 'wpstg'); ?> </a>
|
33 |
+
</div>
|
34 |
+
<?php
|
35 |
+
//print_r( $options->excludedTables);
|
36 |
+
foreach ($options->tables as $table):
|
37 |
+
$attributes = in_array($table->name, $options->excludedTables) ? '' : "checked";
|
38 |
+
$attributes .= in_array($table->name, $options->clonedTables) ? " disabled" : '';
|
39 |
+
?>
|
40 |
+
<div class="wpstg-db-table">
|
41 |
+
<label>
|
42 |
+
<input class="wpstg-db-table-checkboxes" type="checkbox" name="<?php echo $table->name?>" <?php echo $attributes?>>
|
43 |
+
<?php echo $table->name?>
|
44 |
+
</label>
|
45 |
+
<span class="wpstg-size-info">
|
46 |
+
<?php echo $scan->formatSize($table->size)?>
|
47 |
+
</span>
|
48 |
+
</div>
|
49 |
+
<?php endforeach ?>
|
50 |
+
<div style="margin-top:10px;">
|
51 |
+
<a href="#" class="wpstg-button-unselect button"> None </a>
|
52 |
+
<a href="#" class="wpstg-button-select button"> <?php _e(WPStaging\WPStaging::getTablePrefix(), 'wpstg'); ?> </a>
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
|
56 |
+
<a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
|
57 |
+
<span class="wpstg-tab-triangle">►</span>
|
58 |
+
<?php echo __("Files", "wpstg")?>
|
59 |
+
</a>
|
60 |
+
|
61 |
+
<div class="wpstg-tab-section" id="wpstg-scanning-files">
|
62 |
+
<h4 style="margin:0">
|
63 |
+
<?php echo __("Uncheck the folders you do not want to copy. Click on them for expanding!", "wpstg")?>
|
64 |
+
</h4>
|
65 |
+
|
66 |
+
<?php echo $scan->directoryListing()?>
|
67 |
+
|
68 |
+
<h4 style="margin:10px 0 10px 0">
|
69 |
+
<?php echo __("Extra directories to copy", "wpstg")?>
|
70 |
+
</h4>
|
71 |
+
|
72 |
+
<textarea id="wpstg_extraDirectories" name="wpstg_extraDirectories" style="width:100%;height:250px;"></textarea>
|
73 |
+
<p>
|
74 |
+
<span>
|
75 |
+
<?php
|
76 |
+
echo __(
|
77 |
+
"Enter one folder path per line.<br>".
|
78 |
+
"Folders must start with absolute path: " . $options->root,
|
79 |
+
"wpstg"
|
80 |
+
)
|
81 |
+
?>
|
82 |
+
</span>
|
83 |
+
</p>
|
84 |
+
|
85 |
+
<p>
|
86 |
+
<span>
|
87 |
+
<?php
|
88 |
+
if (isset($options->clone)){
|
89 |
+
echo __("All files will be copied to: ", "wpstg") . $options->root . $options->clone;
|
90 |
+
}
|
91 |
+
?>
|
92 |
+
</span>
|
93 |
+
</p>
|
94 |
+
</div>
|
95 |
+
|
96 |
+
<a href="#" class="wpstg-tab-header" data-id="#wpstg-advanced-settings">
|
97 |
+
<span class="wpstg-tab-triangle">►</span>
|
98 |
+
<?php echo __("Advanced Options", "wpstg")?>
|
99 |
+
</a>
|
100 |
+
|
101 |
+
<div class="wpstg-tab-section" id="wpstg-advanced-settings">
|
102 |
+
Coming Soon...
|
103 |
+
</div>
|
104 |
+
|
105 |
+
</div>
|
106 |
+
|
107 |
+
<button type="button" class="wpstg-prev-step-link wpstg-link-btn button-primary">
|
108 |
+
<?php _e("Back", "wpstg")?>
|
109 |
+
</button>
|
110 |
+
|
111 |
+
<?php
|
112 |
+
if (null !== $options->current)
|
113 |
+
{
|
114 |
+
$label = __("Update Clone", "wpstg");
|
115 |
+
$action = 'wpstg_update';
|
116 |
+
|
117 |
+
echo '<button type="button" id="wpstg-start-updating" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="'.$action.'">'.$label.'</button>';
|
118 |
+
}
|
119 |
+
else
|
120 |
+
{
|
121 |
+
$label = __("Start Cloning", "wpstg");
|
122 |
+
$action = 'wpstg_cloning';
|
123 |
+
|
124 |
+
echo '<button type="button" id="wpstg-start-cloning" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="'.$action.'">'.$label.'</button>';
|
125 |
+
|
126 |
+
}
|
127 |
+
?>
|
128 |
+
|
129 |
<a href="#" id="wpstg-check-space"><?php _e('Check Disk Space', 'wpstg'); ?></a>
|
apps/Backend/views/clone/ajax/single-overview.php
CHANGED
@@ -1,56 +1,56 @@
|
|
1 |
-
<div id="wpstg-step-1">
|
2 |
-
<button id="wpstg-new-clone" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="wpstg_scanning">
|
3 |
-
<?php echo __("Create new staging site", "wpstg")?>
|
4 |
-
</button>
|
5 |
-
</div>
|
6 |
-
|
7 |
-
<?php if (isset($availableClones) && !empty($availableClones)):?>
|
8 |
-
<!-- Existing Clones -->
|
9 |
-
<div id="wpstg-existing-clones">
|
10 |
-
<h3>
|
11 |
-
<?php _e("Your Staging Sites:", "wpstg")?>
|
12 |
-
</h3>
|
13 |
-
<?php //wp_die(var_dump($availableClones)); ?>
|
14 |
-
<?php foreach ($availableClones as $name => $data):?>
|
15 |
-
<div id="<?php echo $data["directoryName"]; ?>" class="wpstg-clone">
|
16 |
-
|
17 |
-
<?php $urlLogin = $data["url"] . "/wp-login.php"?>
|
18 |
-
|
19 |
-
<a href="<?php echo $urlLogin?>" class="wpstg-clone-title" target="_blank">
|
20 |
-
<?php //echo $name?>
|
21 |
-
<?php echo $data["directoryName"]; ?>
|
22 |
-
</a>
|
23 |
-
|
24 |
-
<?php echo apply_filters("wpstg_before_stage_buttons", $html = '', $name, $data)?>
|
25 |
-
|
26 |
-
<a href="<?php echo $urlLogin?>" class="wpstg-open-clone wpstg-clone-action" target="_blank">
|
27 |
-
<?php _e("Open", "wpstg"); ?>
|
28 |
-
</a>
|
29 |
-
|
30 |
-
<a href="#" class="wpstg-execute-clone wpstg-clone-action" data-clone="<?php echo $name?>">
|
31 |
-
<?php _e("Update", "wpstg"); ?>
|
32 |
-
</a>
|
33 |
-
|
34 |
-
<a href="#" class="wpstg-remove-clone wpstg-clone-action" data-clone="<?php echo $name?>">
|
35 |
-
<?php _e("Delete", "wpstg"); ?>
|
36 |
-
</a>
|
37 |
-
|
38 |
-
<?php echo apply_filters("wpstg_after_stage_buttons", $html = '', $name, $data)?>
|
39 |
-
<div class="wpstg-staging-info">
|
40 |
-
<?php
|
41 |
-
$prefix = isset ($data['prefix']) ? __("DB prefix: <span class='wpstg-bold'>" . $data['prefix'], "wpstg") . '</span> ' : ' ';
|
42 |
-
//$path = isset ($data['directoryName']) ? __("Subdir: <span class='wpstg-bold'>" . $data['directoryName'], "wpstg") . '</span>' : '';
|
43 |
-
echo $prefix;
|
44 |
-
?>
|
45 |
-
</div>
|
46 |
-
</div>
|
47 |
-
<?php endforeach?>
|
48 |
-
</div>
|
49 |
-
<!-- /Existing Clones -->
|
50 |
-
<?php endif?>
|
51 |
-
|
52 |
-
<!-- Remove Clone -->
|
53 |
-
<div id="wpstg-removing-clone">
|
54 |
-
|
55 |
-
</div>
|
56 |
<!-- /Remove Clone -->
|
1 |
+
<div id="wpstg-step-1">
|
2 |
+
<button id="wpstg-new-clone" class="wpstg-next-step-link wpstg-link-btn button-primary" data-action="wpstg_scanning">
|
3 |
+
<?php echo __("Create new staging site", "wpstg")?>
|
4 |
+
</button>
|
5 |
+
</div>
|
6 |
+
|
7 |
+
<?php if (isset($availableClones) && !empty($availableClones)):?>
|
8 |
+
<!-- Existing Clones -->
|
9 |
+
<div id="wpstg-existing-clones">
|
10 |
+
<h3>
|
11 |
+
<?php _e("Your Staging Sites:", "wpstg")?>
|
12 |
+
</h3>
|
13 |
+
<?php //wp_die(var_dump($availableClones)); ?>
|
14 |
+
<?php foreach ($availableClones as $name => $data):?>
|
15 |
+
<div id="<?php echo $data["directoryName"]; ?>" class="wpstg-clone">
|
16 |
+
|
17 |
+
<?php $urlLogin = $data["url"] . "/wp-login.php"?>
|
18 |
+
|
19 |
+
<a href="<?php echo $urlLogin?>" class="wpstg-clone-title" target="_blank">
|
20 |
+
<?php //echo $name?>
|
21 |
+
<?php echo $data["directoryName"]; ?>
|
22 |
+
</a>
|
23 |
+
|
24 |
+
<?php echo apply_filters("wpstg_before_stage_buttons", $html = '', $name, $data)?>
|
25 |
+
|
26 |
+
<a href="<?php echo $urlLogin?>" class="wpstg-open-clone wpstg-clone-action" target="_blank">
|
27 |
+
<?php _e("Open", "wpstg"); ?>
|
28 |
+
</a>
|
29 |
+
|
30 |
+
<a href="#" class="wpstg-execute-clone wpstg-clone-action" data-clone="<?php echo $name?>">
|
31 |
+
<?php _e("Update", "wpstg"); ?>
|
32 |
+
</a>
|
33 |
+
|
34 |
+
<a href="#" class="wpstg-remove-clone wpstg-clone-action" data-clone="<?php echo $name?>">
|
35 |
+
<?php _e("Delete", "wpstg"); ?>
|
36 |
+
</a>
|
37 |
+
|
38 |
+
<?php echo apply_filters("wpstg_after_stage_buttons", $html = '', $name, $data)?>
|
39 |
+
<div class="wpstg-staging-info">
|
40 |
+
<?php
|
41 |
+
$prefix = isset ($data['prefix']) ? __("DB prefix: <span class='wpstg-bold'>" . $data['prefix'], "wpstg") . '</span> ' : ' ';
|
42 |
+
//$path = isset ($data['directoryName']) ? __("Subdir: <span class='wpstg-bold'>" . $data['directoryName'], "wpstg") . '</span>' : '';
|
43 |
+
echo $prefix;
|
44 |
+
?>
|
45 |
+
</div>
|
46 |
+
</div>
|
47 |
+
<?php endforeach?>
|
48 |
+
</div>
|
49 |
+
<!-- /Existing Clones -->
|
50 |
+
<?php endif?>
|
51 |
+
|
52 |
+
<!-- Remove Clone -->
|
53 |
+
<div id="wpstg-removing-clone">
|
54 |
+
|
55 |
+
</div>
|
56 |
<!-- /Remove Clone -->
|
apps/Backend/views/clone/ajax/start.php
CHANGED
@@ -1,113 +1,113 @@
|
|
1 |
-
<div class=successfullying-section">
|
2 |
-
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
-
<div class="wpstg-progress-bar">
|
4 |
-
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
-
</div>
|
6 |
-
</div>
|
7 |
-
|
8 |
-
<div class="wpstg-cloning-section">
|
9 |
-
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
-
<div class="wpstg-progress-bar">
|
11 |
-
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
-
</div>
|
13 |
-
</div>
|
14 |
-
|
15 |
-
<div class="wpstg-cloning-section">
|
16 |
-
<?php echo __("Copy Files", "wpstg")?>
|
17 |
-
<div class="wpstg-progress-bar">
|
18 |
-
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
-
|
22 |
-
<div class="wpstg-cloning-section">
|
23 |
-
<?php echo __("Replace Data", "wpstg")?>
|
24 |
-
<div class="wpstg-progress-bar">
|
25 |
-
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
|
29 |
-
<button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
|
30 |
-
<?php echo __("Cancel", "wpstg")?>
|
31 |
-
</button>
|
32 |
-
|
33 |
-
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
-
<?php _e('Display working log', 'wpstg')?>
|
35 |
-
</button>
|
36 |
-
|
37 |
-
<div>
|
38 |
-
<span id="wpstg-cloning-result"></span>
|
39 |
-
</div>
|
40 |
-
|
41 |
-
<div id="wpstg-finished-result">
|
42 |
-
<h3>Congratulations
|
43 |
-
</h3>
|
44 |
-
<?php
|
45 |
-
//echo ABSPATH . '<br>';
|
46 |
-
//echo get_home_path();
|
47 |
-
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
48 |
-
$url = get_home_url() . str_replace('/', '', $subDirectory);
|
49 |
-
echo sprintf( __( 'WP Staging successfully created a staging site in a sub-directory of your main site in:<br><strong><a href="%1$s" target="_blank" id="wpstg-clone-url-1">%1$s</a></strong>', 'wpstg' ), $url );
|
50 |
-
?>
|
51 |
-
<br>
|
52 |
-
<?php //echo __('Open and access the staging site: ', 'wpstg')?>
|
53 |
-
<br>
|
54 |
-
<a href="<?php echo $url; ?>" id="wpstg-clone-url" target="_blank" class="wpstg-link-btn button-primary">
|
55 |
-
Open staging site <span style="font-size: 10px;">(login with your admin credentials)</span>
|
56 |
-
</a>
|
57 |
-
<!--<a href="" class="wpstg-link-btn button-primary" id="wpstg-remove-cloning">
|
58 |
-
<?php //echo __("Remove", "wpstg")?>
|
59 |
-
</a>//-->
|
60 |
-
<a href="" class="wpstg-link-btn button-primary" id="wpstg-home-link">
|
61 |
-
<?php echo __("Start again", "wpstg")?>
|
62 |
-
</a>
|
63 |
-
<div id="wpstg-success-notice">
|
64 |
-
<h3 style="margin-top:0px;">
|
65 |
-
<?php _e("Important Notes:", "wpstg")?>
|
66 |
-
</h3>
|
67 |
-
<ul>
|
68 |
-
<li>
|
69 |
-
<strong>1. Permalinks on your <span style="font-style:italic;">staging site</span> will be disabled for technical reasons! </strong>
|
70 |
-
<br>
|
71 |
-
Usually this is no problem for a staging website and you do not need to use permalinks!
|
72 |
-
<br>
|
73 |
-
<p>
|
74 |
-
If you really want permalinks on your staging site you need to do several modifications to your .htaccess (Apache) or *.conf (Nginx).
|
75 |
-
<br>
|
76 |
-
WP Staging can not do this modification automatically.
|
77 |
-
</p>
|
78 |
-
<p>
|
79 |
-
<strong>Read more:</strong>
|
80 |
-
<a href="http://stackoverflow.com/questions/5564881/htaccess-to-rewrite-wordpress-subdirectory-with-permalinks-to-root" target="_blank">
|
81 |
-
Changes .htaccess
|
82 |
-
</a> |
|
83 |
-
<a href="http://robido.com/nginx/nginx-wordpress-subdirectory-configuration-example/" target="_blank">
|
84 |
-
Changes nginx conf
|
85 |
-
</a>
|
86 |
-
</p>
|
87 |
-
</li>
|
88 |
-
<li>
|
89 |
-
<strong>2. Verify that you are REALLY working on your staging site and NOT on your production site if you are uncertain! </strong>
|
90 |
-
<br>
|
91 |
-
Your main and your staging site are both reachable under the same domain so
|
92 |
-
<br>
|
93 |
-
it´s easy to get confused.
|
94 |
-
<p>
|
95 |
-
To assist you we changed the name of the dashboard link to
|
96 |
-
<strong style="font-style:italic;">
|
97 |
-
"STAGING - <span class="wpstg-clone-name"><?php echo get_bloginfo("name")?></span>"
|
98 |
-
</strong>.
|
99 |
-
<br>
|
100 |
-
You will notice this new name in the admin bar:
|
101 |
-
<br><br>
|
102 |
-
<img src="<?php echo $this->url . "/img/admin_dashboard.png" ?>">
|
103 |
-
</p>
|
104 |
-
</li>
|
105 |
-
</ul>
|
106 |
-
</div>
|
107 |
-
</div>
|
108 |
-
|
109 |
-
<div id="wpstg-error-wrapper">
|
110 |
-
<div id="wpstg-error-details"></div>
|
111 |
-
</div>
|
112 |
-
|
113 |
<div id="wpstg-log-details"></div>
|
1 |
+
<div class=successfullying-section">
|
2 |
+
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
+
<div class="wpstg-progress-bar">
|
4 |
+
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
+
</div>
|
6 |
+
</div>
|
7 |
+
|
8 |
+
<div class="wpstg-cloning-section">
|
9 |
+
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
+
<div class="wpstg-progress-bar">
|
11 |
+
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<div class="wpstg-cloning-section">
|
16 |
+
<?php echo __("Copy Files", "wpstg")?>
|
17 |
+
<div class="wpstg-progress-bar">
|
18 |
+
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="wpstg-cloning-section">
|
23 |
+
<?php echo __("Replace Data", "wpstg")?>
|
24 |
+
<div class="wpstg-progress-bar">
|
25 |
+
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<button type="button" id="wpstg-cancel-cloning" class="wpstg-link-btn button-primary">
|
30 |
+
<?php echo __("Cancel", "wpstg")?>
|
31 |
+
</button>
|
32 |
+
|
33 |
+
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
+
<?php _e('Display working log', 'wpstg')?>
|
35 |
+
</button>
|
36 |
+
|
37 |
+
<div>
|
38 |
+
<span id="wpstg-cloning-result"></span>
|
39 |
+
</div>
|
40 |
+
|
41 |
+
<div id="wpstg-finished-result">
|
42 |
+
<h3>Congratulations
|
43 |
+
</h3>
|
44 |
+
<?php
|
45 |
+
//echo ABSPATH . '<br>';
|
46 |
+
//echo get_home_path();
|
47 |
+
$subDirectory = str_replace( get_home_path(), '', ABSPATH );
|
48 |
+
$url = get_home_url() . str_replace('/', '', $subDirectory);
|
49 |
+
echo sprintf( __( 'WP Staging successfully created a staging site in a sub-directory of your main site in:<br><strong><a href="%1$s" target="_blank" id="wpstg-clone-url-1">%1$s</a></strong>', 'wpstg' ), $url );
|
50 |
+
?>
|
51 |
+
<br>
|
52 |
+
<?php //echo __('Open and access the staging site: ', 'wpstg')?>
|
53 |
+
<br>
|
54 |
+
<a href="<?php echo $url; ?>" id="wpstg-clone-url" target="_blank" class="wpstg-link-btn button-primary">
|
55 |
+
Open staging site <span style="font-size: 10px;">(login with your admin credentials)</span>
|
56 |
+
</a>
|
57 |
+
<!--<a href="" class="wpstg-link-btn button-primary" id="wpstg-remove-cloning">
|
58 |
+
<?php //echo __("Remove", "wpstg")?>
|
59 |
+
</a>//-->
|
60 |
+
<a href="" class="wpstg-link-btn button-primary" id="wpstg-home-link">
|
61 |
+
<?php echo __("Start again", "wpstg")?>
|
62 |
+
</a>
|
63 |
+
<div id="wpstg-success-notice">
|
64 |
+
<h3 style="margin-top:0px;">
|
65 |
+
<?php _e("Important Notes:", "wpstg")?>
|
66 |
+
</h3>
|
67 |
+
<ul>
|
68 |
+
<li>
|
69 |
+
<strong>1. Permalinks on your <span style="font-style:italic;">staging site</span> will be disabled for technical reasons! </strong>
|
70 |
+
<br>
|
71 |
+
Usually this is no problem for a staging website and you do not need to use permalinks!
|
72 |
+
<br>
|
73 |
+
<p>
|
74 |
+
If you really want permalinks on your staging site you need to do several modifications to your .htaccess (Apache) or *.conf (Nginx).
|
75 |
+
<br>
|
76 |
+
WP Staging can not do this modification automatically.
|
77 |
+
</p>
|
78 |
+
<p>
|
79 |
+
<strong>Read more:</strong>
|
80 |
+
<a href="http://stackoverflow.com/questions/5564881/htaccess-to-rewrite-wordpress-subdirectory-with-permalinks-to-root" target="_blank">
|
81 |
+
Changes .htaccess
|
82 |
+
</a> |
|
83 |
+
<a href="http://robido.com/nginx/nginx-wordpress-subdirectory-configuration-example/" target="_blank">
|
84 |
+
Changes nginx conf
|
85 |
+
</a>
|
86 |
+
</p>
|
87 |
+
</li>
|
88 |
+
<li>
|
89 |
+
<strong>2. Verify that you are REALLY working on your staging site and NOT on your production site if you are uncertain! </strong>
|
90 |
+
<br>
|
91 |
+
Your main and your staging site are both reachable under the same domain so
|
92 |
+
<br>
|
93 |
+
it´s easy to get confused.
|
94 |
+
<p>
|
95 |
+
To assist you we changed the name of the dashboard link to
|
96 |
+
<strong style="font-style:italic;">
|
97 |
+
"STAGING - <span class="wpstg-clone-name"><?php echo get_bloginfo("name")?></span>"
|
98 |
+
</strong>.
|
99 |
+
<br>
|
100 |
+
You will notice this new name in the admin bar:
|
101 |
+
<br><br>
|
102 |
+
<img src="<?php echo $this->url . "/img/admin_dashboard.png" ?>">
|
103 |
+
</p>
|
104 |
+
</li>
|
105 |
+
</ul>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
|
109 |
+
<div id="wpstg-error-wrapper">
|
110 |
+
<div id="wpstg-error-details"></div>
|
111 |
+
</div>
|
112 |
+
|
113 |
<div id="wpstg-log-details"></div>
|
apps/Backend/views/clone/ajax/update.php
CHANGED
@@ -1,46 +1,46 @@
|
|
1 |
-
<div class=successfullying-section">
|
2 |
-
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
-
<div class="wpstg-progress-bar">
|
4 |
-
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
-
</div>
|
6 |
-
</div>
|
7 |
-
|
8 |
-
<div class="wpstg-cloning-section">
|
9 |
-
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
-
<div class="wpstg-progress-bar">
|
11 |
-
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
-
</div>
|
13 |
-
</div>
|
14 |
-
|
15 |
-
<div class="wpstg-cloning-section">
|
16 |
-
<?php echo __("Copy Files", "wpstg")?>
|
17 |
-
<div class="wpstg-progress-bar">
|
18 |
-
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
-
|
22 |
-
<div class="wpstg-cloning-section">
|
23 |
-
<?php echo __("Replace Data", "wpstg")?>
|
24 |
-
<div class="wpstg-progress-bar">
|
25 |
-
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
|
29 |
-
<button type="button" id="wpstg-cancel-cloning-update" class="wpstg-link-btn button-primary">
|
30 |
-
<?php echo __("Cancel Update", "wpstg")?>
|
31 |
-
</button>
|
32 |
-
|
33 |
-
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
-
<?php _e('Display working log', 'wpstg')?>
|
35 |
-
</button>
|
36 |
-
|
37 |
-
<div>
|
38 |
-
<span id="wpstg-cloning-result"></span>
|
39 |
-
</div>
|
40 |
-
|
41 |
-
|
42 |
-
<div id="wpstg-error-wrapper">
|
43 |
-
<div id="wpstg-error-details"></div>
|
44 |
-
</div>
|
45 |
-
|
46 |
<div id="wpstg-log-details"></div>
|
1 |
+
<div class=successfullying-section">
|
2 |
+
<?php echo __("Copy Database Tables", "wpstg")?>
|
3 |
+
<div class="wpstg-progress-bar">
|
4 |
+
<div class="wpstg-progress" id="wpstg-db-progress" style="width:0"></div>
|
5 |
+
</div>
|
6 |
+
</div>
|
7 |
+
|
8 |
+
<div class="wpstg-cloning-section">
|
9 |
+
<?php echo __("Prepare Directories", "wpstg")?>
|
10 |
+
<div class="wpstg-progress-bar">
|
11 |
+
<div class="wpstg-progress" id="wpstg-directories-progress" style="width:0"></div>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<div class="wpstg-cloning-section">
|
16 |
+
<?php echo __("Copy Files", "wpstg")?>
|
17 |
+
<div class="wpstg-progress-bar">
|
18 |
+
<div class="wpstg-progress" id="wpstg-files-progress" style="width:0"></div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="wpstg-cloning-section">
|
23 |
+
<?php echo __("Replace Data", "wpstg")?>
|
24 |
+
<div class="wpstg-progress-bar">
|
25 |
+
<div class="wpstg-progress" id="wpstg-links-progress" style="width:0"></div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<button type="button" id="wpstg-cancel-cloning-update" class="wpstg-link-btn button-primary">
|
30 |
+
<?php echo __("Cancel Update", "wpstg")?>
|
31 |
+
</button>
|
32 |
+
|
33 |
+
<button type="button" id="wpstg-show-log-button" class="button" data-clone="<?php echo $cloning->getOptions()->clone?>" style="margin-top: 5px;display:none;">
|
34 |
+
<?php _e('Display working log', 'wpstg')?>
|
35 |
+
</button>
|
36 |
+
|
37 |
+
<div>
|
38 |
+
<span id="wpstg-cloning-result"></span>
|
39 |
+
</div>
|
40 |
+
|
41 |
+
|
42 |
+
<div id="wpstg-error-wrapper">
|
43 |
+
<div id="wpstg-error-details"></div>
|
44 |
+
</div>
|
45 |
+
|
46 |
<div id="wpstg-log-details"></div>
|
apps/Backend/views/settings/index.php
CHANGED
@@ -99,7 +99,7 @@
|
|
99 |
To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it
|
100 |
until you get no more errors during copying process.
|
101 |
<br>
|
102 |
-
<strong> Default:
|
103 |
</span>
|
104 |
</div>
|
105 |
</td>
|
99 |
To find out the highest possible values try a high value like 1.000 or more. If you get timeout issues, lower it
|
100 |
until you get no more errors during copying process.
|
101 |
<br>
|
102 |
+
<strong> Default: 5000 </strong>
|
103 |
</span>
|
104 |
</div>
|
105 |
</td>
|
apps/Core/Iterators/RecursiveDirectoryIterator.php
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Iterators;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if (!defined("WPINC")) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator {
|
11 |
-
|
12 |
-
protected $exclude = array();
|
13 |
-
|
14 |
-
public function __construct( $path ) {
|
15 |
-
parent::__construct( $path );
|
16 |
-
|
17 |
-
// Skip current and parent directory
|
18 |
-
$this->skipdots();
|
19 |
-
}
|
20 |
-
|
21 |
-
public function rewind() {
|
22 |
-
parent::rewind();
|
23 |
-
|
24 |
-
// Skip current and parent directory
|
25 |
-
$this->skipdots();
|
26 |
-
}
|
27 |
-
|
28 |
-
public function next() {
|
29 |
-
parent::next();
|
30 |
-
|
31 |
-
// Skip current and parent directory
|
32 |
-
$this->skipdots();
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Returns whether current entry is a directory and not '.' or '..'
|
37 |
-
*
|
38 |
-
* Explicitly set allow links flag, because RecursiveDirectoryIterator::FOLLOW_SYMLINKS
|
39 |
-
* is not supported by <= PHP 5.3.0
|
40 |
-
*
|
41 |
-
* @return bool
|
42 |
-
*/
|
43 |
-
public function hasChildren( $allow_links = true ) {
|
44 |
-
return parent::hasChildren( $allow_links );
|
45 |
-
}
|
46 |
-
|
47 |
-
protected function skipdots() {
|
48 |
-
while ( $this->isDot() ) {
|
49 |
-
parent::next();
|
50 |
-
}
|
51 |
-
}
|
52 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Iterators;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if (!defined("WPINC")) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator {
|
11 |
+
|
12 |
+
protected $exclude = array();
|
13 |
+
|
14 |
+
public function __construct( $path ) {
|
15 |
+
parent::__construct( $path );
|
16 |
+
|
17 |
+
// Skip current and parent directory
|
18 |
+
$this->skipdots();
|
19 |
+
}
|
20 |
+
|
21 |
+
public function rewind() {
|
22 |
+
parent::rewind();
|
23 |
+
|
24 |
+
// Skip current and parent directory
|
25 |
+
$this->skipdots();
|
26 |
+
}
|
27 |
+
|
28 |
+
public function next() {
|
29 |
+
parent::next();
|
30 |
+
|
31 |
+
// Skip current and parent directory
|
32 |
+
$this->skipdots();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Returns whether current entry is a directory and not '.' or '..'
|
37 |
+
*
|
38 |
+
* Explicitly set allow links flag, because RecursiveDirectoryIterator::FOLLOW_SYMLINKS
|
39 |
+
* is not supported by <= PHP 5.3.0
|
40 |
+
*
|
41 |
+
* @return bool
|
42 |
+
*/
|
43 |
+
public function hasChildren( $allow_links = true ) {
|
44 |
+
return parent::hasChildren( $allow_links );
|
45 |
+
}
|
46 |
+
|
47 |
+
protected function skipdots() {
|
48 |
+
while ( $this->isDot() ) {
|
49 |
+
parent::next();
|
50 |
+
}
|
51 |
+
}
|
52 |
+
}
|
apps/Core/Iterators/RecursiveFilterExclude.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Iterators;
|
4 |
-
|
5 |
-
class RecursiveFilterExclude extends \RecursiveFilterIterator {
|
6 |
-
|
7 |
-
protected $exclude = array();
|
8 |
-
|
9 |
-
public function __construct( \RecursiveIterator $iterator, $exclude = array() ) {
|
10 |
-
parent::__construct( $iterator );
|
11 |
-
|
12 |
-
// Set exclude filter
|
13 |
-
$this->exclude = $exclude;
|
14 |
-
}
|
15 |
-
|
16 |
-
public function accept() {
|
17 |
-
return ! in_array( $this->getInnerIterator()->getSubPathname(), $this->exclude );
|
18 |
-
}
|
19 |
-
|
20 |
-
public function getChildren() {
|
21 |
-
return new self( $this->getInnerIterator()->getChildren(), $this->exclude );
|
22 |
-
}
|
23 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Iterators;
|
4 |
+
|
5 |
+
class RecursiveFilterExclude extends \RecursiveFilterIterator {
|
6 |
+
|
7 |
+
protected $exclude = array();
|
8 |
+
|
9 |
+
public function __construct( \RecursiveIterator $iterator, $exclude = array() ) {
|
10 |
+
parent::__construct( $iterator );
|
11 |
+
|
12 |
+
// Set exclude filter
|
13 |
+
$this->exclude = $exclude;
|
14 |
+
}
|
15 |
+
|
16 |
+
public function accept() {
|
17 |
+
return ! in_array( $this->getInnerIterator()->getSubPathname(), $this->exclude );
|
18 |
+
}
|
19 |
+
|
20 |
+
public function getChildren() {
|
21 |
+
return new self( $this->getInnerIterator()->getChildren(), $this->exclude );
|
22 |
+
}
|
23 |
+
}
|
apps/Core/Iterators/RecursiveFilterNewLine.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Iterators;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if (!defined("WPINC")) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Filter files which contain new line character in name
|
12 |
-
*/
|
13 |
-
|
14 |
-
class RecursiveFilterNewLine extends \RecursiveFilterIterator {
|
15 |
-
|
16 |
-
public function accept() {
|
17 |
-
return strpos( $this->getInnerIterator()->getSubPathname(), "\n" ) === false &&
|
18 |
-
strpos( $this->getInnerIterator()->getSubPathname(), "\r" ) === false;
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Iterators;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if (!defined("WPINC")) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Filter files which contain new line character in name
|
12 |
+
*/
|
13 |
+
|
14 |
+
class RecursiveFilterNewLine extends \RecursiveFilterIterator {
|
15 |
+
|
16 |
+
public function accept() {
|
17 |
+
return strpos( $this->getInnerIterator()->getSubPathname(), "\n" ) === false &&
|
18 |
+
strpos( $this->getInnerIterator()->getSubPathname(), "\r" ) === false;
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
apps/Core/Utils/Cache.php
CHANGED
@@ -1,212 +1,212 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPStaging\Utils;
|
3 |
-
|
4 |
-
// No Direct Access
|
5 |
-
if (!defined("WPINC"))
|
6 |
-
{
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
use WPStaging\WPStaging;
|
11 |
-
use WPStaging\Backend\Modules\Jobs;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Class Cache
|
15 |
-
* @package WPStaging\Utils
|
16 |
-
*/
|
17 |
-
class Cache
|
18 |
-
{
|
19 |
-
/**
|
20 |
-
* Cache directory (full path)
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
private $cacheDir;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Cache file extension
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
private $cacheExtension = "cache";
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Lifetime of cache files in seconds
|
33 |
-
* @var int
|
34 |
-
*/
|
35 |
-
private $lifetime = 2592000; // 30 days
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Cache constructor.
|
39 |
-
* @param null|int $lifetime
|
40 |
-
* @param null|string $cacheDir
|
41 |
-
* @param null|string $cacheExtension
|
42 |
-
* @throws \Exception
|
43 |
-
*/
|
44 |
-
public function __construct($lifetime = null, $cacheDir = null, $cacheExtension = null)
|
45 |
-
{
|
46 |
-
// Set lifetime
|
47 |
-
$lifetime = (int) $lifetime;
|
48 |
-
if ($lifetime > 0)
|
49 |
-
{
|
50 |
-
$this->lifetime = $lifetime;
|
51 |
-
}
|
52 |
-
|
53 |
-
// Set cache directory
|
54 |
-
if (!empty($cacheDir) && is_dir($cacheDir))
|
55 |
-
{
|
56 |
-
$this->cacheDir = $cacheDir;
|
57 |
-
}
|
58 |
-
// Set default
|
59 |
-
else
|
60 |
-
{
|
61 |
-
|
62 |
-
$this->cacheDir = \WPStaging\WPStaging::getContentDir();
|
63 |
-
}
|
64 |
-
|
65 |
-
// Set cache extension
|
66 |
-
if (!empty($cacheExtension))
|
67 |
-
{
|
68 |
-
$this->cacheExtension = $cacheExtension;
|
69 |
-
}
|
70 |
-
|
71 |
-
// If cache directory doesn't exists, create it
|
72 |
-
if (!is_dir($this->cacheDir) && !@mkdir($this->cacheDir, 0775, true))
|
73 |
-
{
|
74 |
-
throw new \Exception("Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.');
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Get cache
|
80 |
-
* @param string $cacheFileName
|
81 |
-
* @param mixed $defaultValue
|
82 |
-
* @param null|int $lifetime
|
83 |
-
* @return mixed|null
|
84 |
-
*/
|
85 |
-
public function get($cacheFileName, $defaultValue = null, $lifetime = null)
|
86 |
-
{
|
87 |
-
// Check if file is valid
|
88 |
-
if (false === ($cacheFile = $this->isValid($cacheFileName, true, $lifetime)))
|
89 |
-
{
|
90 |
-
return $defaultValue;
|
91 |
-
}
|
92 |
-
|
93 |
-
return @unserialize(file_get_contents($cacheFile));
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Saves value to given cache file
|
98 |
-
* @param string $cacheFileName
|
99 |
-
* @param mixed $value
|
100 |
-
* @return bool
|
101 |
-
* @throws \Exception
|
102 |
-
*/
|
103 |
-
public function save($cacheFileName, $value)
|
104 |
-
{
|
105 |
-
$cacheFile = $this->cacheDir . $cacheFileName . '.' . $this->cacheExtension;
|
106 |
-
|
107 |
-
// Attempt to delete cache file if it exists
|
108 |
-
if (is_file($cacheFile) && !@unlink($cacheFile))
|
109 |
-
{
|
110 |
-
$this->returnException("Can't delete existing cache file");
|
111 |
-
throw new \Exception("Can't delete existing cache file");
|
112 |
-
}
|
113 |
-
|
114 |
-
// Save it to file
|
115 |
-
return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
116 |
-
//return (file_put_contents($cacheFile, @serialize($value)) !== false);
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
* Throw a errror message via json and stop further execution
|
121 |
-
* @param string $message
|
122 |
-
*/
|
123 |
-
protected function returnException($message = ''){
|
124 |
-
wp_die( json_encode(array(
|
125 |
-
'job' => isset($this->options->currentJob) ? $this->options->currentJob : '',
|
126 |
-
'status' => false,
|
127 |
-
'message' => $message,
|
128 |
-
'error' => true
|
129 |
-
)));
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
-
* Checks if file is valid or not
|
134 |
-
* @param $cacheFileName
|
135 |
-
* @param bool $deleteFileIfInvalid
|
136 |
-
* @param null|int $lifetime
|
137 |
-
* @return string|bool
|
138 |
-
* @throws \Exception
|
139 |
-
*/
|
140 |
-
public function isValid($cacheFileName, $deleteFileIfInvalid = false, $lifetime = null)
|
141 |
-
{
|
142 |
-
// Lifetime
|
143 |
-
$lifetime = (int) $lifetime;
|
144 |
-
if (-1 > $lifetime || 0 == $lifetime)
|
145 |
-
{
|
146 |
-
$lifetime = $this->lifetime;
|
147 |
-
}
|
148 |
-
|
149 |
-
// Get full path of the given cache file
|
150 |
-
$cacheFile = $this->cacheDir . $cacheFileName . '.' . $this->cacheExtension;
|
151 |
-
|
152 |
-
// File doesn't exist
|
153 |
-
if (!is_file($cacheFile))
|
154 |
-
{
|
155 |
-
return false;
|
156 |
-
}
|
157 |
-
|
158 |
-
// As long as file exists, don't check lifetime
|
159 |
-
if (-1 == $lifetime)
|
160 |
-
{
|
161 |
-
return $cacheFile;
|
162 |
-
}
|
163 |
-
|
164 |
-
// Time is up, file is invalid
|
165 |
-
if (time() - filemtime($cacheFile) >= $lifetime)
|
166 |
-
{
|
167 |
-
|
168 |
-
// Attempt to delete the file
|
169 |
-
if ($deleteFileIfInvalid === true && !@unlink($cacheFile))
|
170 |
-
{
|
171 |
-
throw new \Exception("Attempting to delete invalid cache file has failed!");
|
172 |
-
}
|
173 |
-
|
174 |
-
// No need to delete the file, return
|
175 |
-
return false;
|
176 |
-
}
|
177 |
-
|
178 |
-
return $cacheFile;
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Delete a cache file
|
183 |
-
* @param string $cacheFileName
|
184 |
-
* @return bool
|
185 |
-
* @throws \Exception
|
186 |
-
*/
|
187 |
-
public function delete($cacheFileName)
|
188 |
-
{
|
189 |
-
if (false !== ($cacheFile = $this->isValid($cacheFileName, true)) && false === @unlink($cacheFile))
|
190 |
-
{
|
191 |
-
throw new \Exception("Couldn't delete cache: {$cacheFileName}. Full Path: {$cacheFile}");
|
192 |
-
}
|
193 |
-
|
194 |
-
return true;
|
195 |
-
}
|
196 |
-
|
197 |
-
/**
|
198 |
-
* @return string
|
199 |
-
*/
|
200 |
-
public function getCacheDir()
|
201 |
-
{
|
202 |
-
return $this->cacheDir;
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* @return string
|
207 |
-
*/
|
208 |
-
public function getCacheExtension()
|
209 |
-
{
|
210 |
-
return $this->cacheExtension;
|
211 |
-
}
|
212 |
}
|
1 |
+
<?php
|
2 |
+
namespace WPStaging\Utils;
|
3 |
+
|
4 |
+
// No Direct Access
|
5 |
+
if (!defined("WPINC"))
|
6 |
+
{
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
use WPStaging\WPStaging;
|
11 |
+
use WPStaging\Backend\Modules\Jobs;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class Cache
|
15 |
+
* @package WPStaging\Utils
|
16 |
+
*/
|
17 |
+
class Cache
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Cache directory (full path)
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
private $cacheDir;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Cache file extension
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
private $cacheExtension = "cache";
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Lifetime of cache files in seconds
|
33 |
+
* @var int
|
34 |
+
*/
|
35 |
+
private $lifetime = 2592000; // 30 days
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Cache constructor.
|
39 |
+
* @param null|int $lifetime
|
40 |
+
* @param null|string $cacheDir
|
41 |
+
* @param null|string $cacheExtension
|
42 |
+
* @throws \Exception
|
43 |
+
*/
|
44 |
+
public function __construct($lifetime = null, $cacheDir = null, $cacheExtension = null)
|
45 |
+
{
|
46 |
+
// Set lifetime
|
47 |
+
$lifetime = (int) $lifetime;
|
48 |
+
if ($lifetime > 0)
|
49 |
+
{
|
50 |
+
$this->lifetime = $lifetime;
|
51 |
+
}
|
52 |
+
|
53 |
+
// Set cache directory
|
54 |
+
if (!empty($cacheDir) && is_dir($cacheDir))
|
55 |
+
{
|
56 |
+
$this->cacheDir = $cacheDir;
|
57 |
+
}
|
58 |
+
// Set default
|
59 |
+
else
|
60 |
+
{
|
61 |
+
|
62 |
+
$this->cacheDir = \WPStaging\WPStaging::getContentDir();
|
63 |
+
}
|
64 |
+
|
65 |
+
// Set cache extension
|
66 |
+
if (!empty($cacheExtension))
|
67 |
+
{
|
68 |
+
$this->cacheExtension = $cacheExtension;
|
69 |
+
}
|
70 |
+
|
71 |
+
// If cache directory doesn't exists, create it
|
72 |
+
if (!is_dir($this->cacheDir) && !@mkdir($this->cacheDir, 0775, true))
|
73 |
+
{
|
74 |
+
throw new \Exception("Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.');
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get cache
|
80 |
+
* @param string $cacheFileName
|
81 |
+
* @param mixed $defaultValue
|
82 |
+
* @param null|int $lifetime
|
83 |
+
* @return mixed|null
|
84 |
+
*/
|
85 |
+
public function get($cacheFileName, $defaultValue = null, $lifetime = null)
|
86 |
+
{
|
87 |
+
// Check if file is valid
|
88 |
+
if (false === ($cacheFile = $this->isValid($cacheFileName, true, $lifetime)))
|
89 |
+
{
|
90 |
+
return $defaultValue;
|
91 |
+
}
|
92 |
+
|
93 |
+
return @unserialize(file_get_contents($cacheFile));
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Saves value to given cache file
|
98 |
+
* @param string $cacheFileName
|
99 |
+
* @param mixed $value
|
100 |
+
* @return bool
|
101 |
+
* @throws \Exception
|
102 |
+
*/
|
103 |
+
public function save($cacheFileName, $value)
|
104 |
+
{
|
105 |
+
$cacheFile = $this->cacheDir . $cacheFileName . '.' . $this->cacheExtension;
|
106 |
+
|
107 |
+
// Attempt to delete cache file if it exists
|
108 |
+
if (is_file($cacheFile) && !@unlink($cacheFile))
|
109 |
+
{
|
110 |
+
$this->returnException("Can't delete existing cache file");
|
111 |
+
throw new \Exception("Can't delete existing cache file");
|
112 |
+
}
|
113 |
+
|
114 |
+
// Save it to file
|
115 |
+
return (file_put_contents($cacheFile, @serialize($value), LOCK_EX) !== false);
|
116 |
+
//return (file_put_contents($cacheFile, @serialize($value)) !== false);
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Throw a errror message via json and stop further execution
|
121 |
+
* @param string $message
|
122 |
+
*/
|
123 |
+
protected function returnException($message = ''){
|
124 |
+
wp_die( json_encode(array(
|
125 |
+
'job' => isset($this->options->currentJob) ? $this->options->currentJob : '',
|
126 |
+
'status' => false,
|
127 |
+
'message' => $message,
|
128 |
+
'error' => true
|
129 |
+
)));
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Checks if file is valid or not
|
134 |
+
* @param $cacheFileName
|
135 |
+
* @param bool $deleteFileIfInvalid
|
136 |
+
* @param null|int $lifetime
|
137 |
+
* @return string|bool
|
138 |
+
* @throws \Exception
|
139 |
+
*/
|
140 |
+
public function isValid($cacheFileName, $deleteFileIfInvalid = false, $lifetime = null)
|
141 |
+
{
|
142 |
+
// Lifetime
|
143 |
+
$lifetime = (int) $lifetime;
|
144 |
+
if (-1 > $lifetime || 0 == $lifetime)
|
145 |
+
{
|
146 |
+
$lifetime = $this->lifetime;
|
147 |
+
}
|
148 |
+
|
149 |
+
// Get full path of the given cache file
|
150 |
+
$cacheFile = $this->cacheDir . $cacheFileName . '.' . $this->cacheExtension;
|
151 |
+
|
152 |
+
// File doesn't exist
|
153 |
+
if (!is_file($cacheFile))
|
154 |
+
{
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
|
158 |
+
// As long as file exists, don't check lifetime
|
159 |
+
if (-1 == $lifetime)
|
160 |
+
{
|
161 |
+
return $cacheFile;
|
162 |
+
}
|
163 |
+
|
164 |
+
// Time is up, file is invalid
|
165 |
+
if (time() - filemtime($cacheFile) >= $lifetime)
|
166 |
+
{
|
167 |
+
|
168 |
+
// Attempt to delete the file
|
169 |
+
if ($deleteFileIfInvalid === true && !@unlink($cacheFile))
|
170 |
+
{
|
171 |
+
throw new \Exception("Attempting to delete invalid cache file has failed!");
|
172 |
+
}
|
173 |
+
|
174 |
+
// No need to delete the file, return
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
|
178 |
+
return $cacheFile;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Delete a cache file
|
183 |
+
* @param string $cacheFileName
|
184 |
+
* @return bool
|
185 |
+
* @throws \Exception
|
186 |
+
*/
|
187 |
+
public function delete($cacheFileName)
|
188 |
+
{
|
189 |
+
if (false !== ($cacheFile = $this->isValid($cacheFileName, true)) && false === @unlink($cacheFile))
|
190 |
+
{
|
191 |
+
throw new \Exception("Couldn't delete cache: {$cacheFileName}. Full Path: {$cacheFile}");
|
192 |
+
}
|
193 |
+
|
194 |
+
return true;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* @return string
|
199 |
+
*/
|
200 |
+
public function getCacheDir()
|
201 |
+
{
|
202 |
+
return $this->cacheDir;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* @return string
|
207 |
+
*/
|
208 |
+
public function getCacheExtension()
|
209 |
+
{
|
210 |
+
return $this->cacheExtension;
|
211 |
+
}
|
212 |
}
|
apps/Core/Utils/Strings.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Utils;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
class Strings{
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Replace first occurance of certain string
|
14 |
+
* @param string $search
|
15 |
+
* @param string $replace
|
16 |
+
* @param string $subject
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public function str_replace_first( $search, $replace, $subject ) {
|
20 |
+
$pos = strpos( $subject, $search );
|
21 |
+
if( $pos !== false ) {
|
22 |
+
return substr_replace( $subject, $replace, $pos, strlen( $search ) );
|
23 |
+
}
|
24 |
+
return $subject;
|
25 |
+
}
|
26 |
+
|
27 |
+
}
|
apps/Core/WPStaging.php
CHANGED
@@ -1,429 +1,429 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging;
|
4 |
-
|
5 |
-
// No Direct Access
|
6 |
-
if( !defined( "WPINC" ) ) {
|
7 |
-
die;
|
8 |
-
}
|
9 |
-
|
10 |
-
// Ensure to include autoloader class
|
11 |
-
require_once __DIR__ . DIRECTORY_SEPARATOR . "Utils" . DIRECTORY_SEPARATOR . "Autoloader.php";
|
12 |
-
|
13 |
-
use WPStaging\Backend\Administrator;
|
14 |
-
use WPStaging\DTO\Settings;
|
15 |
-
use WPStaging\Frontend\Frontend;
|
16 |
-
use WPStaging\Utils\Autoloader;
|
17 |
-
use WPStaging\Utils\Cache;
|
18 |
-
use WPStaging\Utils\Loader;
|
19 |
-
use WPStaging\Utils\Logger;
|
20 |
-
use WPStaging\DI\InjectionAware;
|
21 |
-
use WPStaging\Cron\Cron;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Class WPStaging
|
25 |
-
* @package WPStaging
|
26 |
-
*/
|
27 |
-
final class WPStaging {
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Plugin version
|
31 |
-
*/
|
32 |
-
const VERSION = "2.1.
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Plugin name
|
36 |
-
*/
|
37 |
-
const NAME = "WP Staging";
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Plugin slug
|
41 |
-
*/
|
42 |
-
const SLUG = "wp-staging";
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Compatible WP Version
|
46 |
-
*/
|
47 |
-
const WP_COMPATIBLE = "4.9.
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Slug: Either wp-staging or wp-staging-pro
|
51 |
-
* @var string
|
52 |
-
*/
|
53 |
-
public $slug;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Absolute plugin path
|
57 |
-
* @var string
|
58 |
-
*/
|
59 |
-
public $pluginPath;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Services
|
63 |
-
* @var array
|
64 |
-
*/
|
65 |
-
private $services;
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Singleton instance
|
69 |
-
* @var WPStaging
|
70 |
-
*/
|
71 |
-
private static $instance;
|
72 |
-
|
73 |
-
/**
|
74 |
-
* WPStaging constructor.
|
75 |
-
*/
|
76 |
-
private function __construct() {
|
77 |
-
|
78 |
-
$file = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . self::SLUG . DIRECTORY_SEPARATOR . self::SLUG . ".php";
|
79 |
-
|
80 |
-
$this->registerMain();
|
81 |
-
$this->registerNamespaces();
|
82 |
-
$this->loadLanguages();
|
83 |
-
$this->loadDependencies();
|
84 |
-
$this->defineHooks();
|
85 |
-
// Licensing stuff be loaded in wpstg core to make cron hook available from frontpage
|
86 |
-
$this->initLicensing();
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Method to be executed upon activation of the plugin
|
91 |
-
*/
|
92 |
-
public function onActivation() {
|
93 |
-
$Activation = new \WPStaging\Backend\Activation\Activation();
|
94 |
-
$Activation->install_dependancies();
|
95 |
-
}
|
96 |
-
|
97 |
-
public function registerMain() {
|
98 |
-
// Slug of the plugin
|
99 |
-
$this->slug = plugin_basename( dirname( dirname( dirname( __FILE__ ) ) ) );
|
100 |
-
|
101 |
-
// absolute path to the main plugin dir
|
102 |
-
$this->pluginPath = plugin_dir_path( dirname( dirname( __FILE__ ) ) );
|
103 |
-
|
104 |
-
// URL to apps folder
|
105 |
-
$this->url = plugin_dir_url( dirname( __FILE__ ) );
|
106 |
-
|
107 |
-
// URL to backend public folder folder
|
108 |
-
$this->backend_url = plugin_dir_url( dirname( __FILE__ ) ) . "Backend/public/";
|
109 |
-
|
110 |
-
// URL to frontend public folder folder
|
111 |
-
$this->frontend_url = plugin_dir_url( dirname( __FILE__ ) ) . "Frontend/public/";
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* Define Hooks
|
116 |
-
*/
|
117 |
-
public function defineHooks() {
|
118 |
-
$loader = $this->get( "loader" );
|
119 |
-
$loader->addAction( "admin_enqueue_scripts", $this, "enqueueElements", 100 );
|
120 |
-
$loader->addAction( "wp_enqueue_scripts", $this, "enqueueElements", 100 );
|
121 |
-
$this->addIntervals();
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Add new cron time event "weekly"
|
126 |
-
*/
|
127 |
-
public function addIntervals(){
|
128 |
-
$interval = new Cron();
|
129 |
-
}
|
130 |
-
|
131 |
-
/**
|
132 |
-
* Scripts and Styles
|
133 |
-
* @param string $hook
|
134 |
-
*/
|
135 |
-
public function enqueueElements( $hook ) {
|
136 |
-
|
137 |
-
// Load this css file on frontend and backend on all pages if current site is a staging site
|
138 |
-
if( $this->isStagingSite() ) {
|
139 |
-
wp_enqueue_style( "wpstg-admin-bar", $this->backend_url . "css/wpstg-admin-bar.css", $this->getVersion() );
|
140 |
-
}
|
141 |
-
|
142 |
-
$availablePages = array(
|
143 |
-
"toplevel_page_wpstg_clone",
|
144 |
-
"wp-staging_page_wpstg-settings",
|
145 |
-
"wp-staging_page_wpstg-tools",
|
146 |
-
"wp-staging_page_wpstg-license",
|
147 |
-
"wp-staging_page_wpstg-welcome",
|
148 |
-
);
|
149 |
-
|
150 |
-
// Load these css and js files only on wp staging admin pages
|
151 |
-
if( !in_array( $hook, $availablePages ) || !is_admin() ) {
|
152 |
-
return;
|
153 |
-
}
|
154 |
-
|
155 |
-
// Load admin js files
|
156 |
-
wp_enqueue_script(
|
157 |
-
"wpstg-admin-script", $this->backend_url . "js/wpstg-admin.js", array("jquery"), $this->getVersion(), false
|
158 |
-
);
|
159 |
-
|
160 |
-
// Load admin css files
|
161 |
-
wp_enqueue_style(
|
162 |
-
"wpstg-admin", $this->backend_url . "css/wpstg-admin.css", $this->getVersion()
|
163 |
-
);
|
164 |
-
|
165 |
-
wp_localize_script( "wpstg-admin-script", "wpstg", array(
|
166 |
-
"nonce" => wp_create_nonce( "wpstg_ajax_nonce" ),
|
167 |
-
"mu_plugin_confirmation" => __(
|
168 |
-
"If confirmed we will install an additional WordPress 'Must Use' plugin. "
|
169 |
-
. "This plugin will allow us to control which plugins are loaded during "
|
170 |
-
. "WP Staging specific operations. Do you wish to continue?", "wpstg"
|
171 |
-
),
|
172 |
-
"plugin_compatibility_settings_problem" => __(
|
173 |
-
"A problem occurred when trying to change the plugin compatibility setting.", "wpstg"
|
174 |
-
),
|
175 |
-
"saved" => __( "Saved", "The settings were saved successfully", "wpstg" ),
|
176 |
-
"status" => __( "Status", "Current request status", "wpstg" ),
|
177 |
-
"response" => __( "Response", "The message the server responded with", "wpstg" ),
|
178 |
-
"blacklist_problem" => __(
|
179 |
-
"A problem occurred when trying to add plugins to backlist.", "wpstg"
|
180 |
-
),
|
181 |
-
"cpuLoad" => $this->getCPULoadSetting(),
|
182 |
-
"settings" => ( object ) array(), // TODO add settings?
|
183 |
-
"tblprefix" => self::getTablePrefix()
|
184 |
-
) );
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Get table prefix of the current site
|
189 |
-
* @return string
|
190 |
-
*/
|
191 |
-
public static function getTablePrefix(){
|
192 |
-
$wpDB = WPStaging::getInstance()->get("wpdb");
|
193 |
-
return $wpDB->prefix;
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* Caching and logging folder
|
198 |
-
*
|
199 |
-
* @return string
|
200 |
-
*/
|
201 |
-
public static function getContentDir() {
|
202 |
-
$wp_upload_dir = wp_upload_dir();
|
203 |
-
$path = $wp_upload_dir['basedir'] . '/wp-staging';
|
204 |
-
wp_mkdir_p( $path );
|
205 |
-
return apply_filters( 'wpstg_get_upload_dir', $path . DIRECTORY_SEPARATOR );
|
206 |
-
}
|
207 |
-
|
208 |
-
/**
|
209 |
-
* Register used namespaces
|
210 |
-
*/
|
211 |
-
private function registerNamespaces() {
|
212 |
-
$autoloader = new Autoloader();
|
213 |
-
$this->set( "autoloader", $autoloader );
|
214 |
-
|
215 |
-
// Autoloader
|
216 |
-
$autoloader->registerNamespaces( array(
|
217 |
-
"WPStaging" => array(
|
218 |
-
$this->pluginPath . 'apps' . DIRECTORY_SEPARATOR,
|
219 |
-
$this->pluginPath . 'apps' . DIRECTORY_SEPARATOR . 'Core' . DIRECTORY_SEPARATOR,
|
220 |
-
)
|
221 |
-
) );
|
222 |
-
|
223 |
-
// Register namespaces
|
224 |
-
$autoloader->register();
|
225 |
-
}
|
226 |
-
|
227 |
-
/**
|
228 |
-
* Get Instance
|
229 |
-
* @return WPStaging
|
230 |
-
*/
|
231 |
-
public static function getInstance() {
|
232 |
-
if( null === static::$instance ) {
|
233 |
-
static::$instance = new static();
|
234 |
-
}
|
235 |
-
|
236 |
-
return static::$instance;
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Prevent cloning
|
241 |
-
* @return void
|
242 |
-
*/
|
243 |
-
private function __clone() {
|
244 |
-
|
245 |
-
}
|
246 |
-
|
247 |
-
/**
|
248 |
-
* Prevent unserialization
|
249 |
-
* @return void
|
250 |
-
*/
|
251 |
-
private function __wakeup() {
|
252 |
-
|
253 |
-
}
|
254 |
-
|
255 |
-
/**
|
256 |
-
* Load Dependencies
|
257 |
-
*/
|
258 |
-
private function loadDependencies() {
|
259 |
-
// Set loader
|
260 |
-
$this->set( "loader", new Loader() );
|
261 |
-
|
262 |
-
// Set cache
|
263 |
-
$this->set( "cache", new Cache() );
|
264 |
-
|
265 |
-
// Set logger
|
266 |
-
$this->set( "logger", new Logger() );
|
267 |
-
|
268 |
-
// Set settings
|
269 |
-
$this->set( "settings", new Settings() );
|
270 |
-
|
271 |
-
// Set Administrator
|
272 |
-
if( is_admin() ) {
|
273 |
-
new Administrator( $this );
|
274 |
-
} else {
|
275 |
-
new Frontend( $this );
|
276 |
-
}
|
277 |
-
}
|
278 |
-
|
279 |
-
/**
|
280 |
-
* Execute Plugin
|
281 |
-
*/
|
282 |
-
public function run() {
|
283 |
-
$this->get( "loader" )->run();
|
284 |
-
}
|
285 |
-
|
286 |
-
/**
|
287 |
-
* Set a variable to DI with given name
|
288 |
-
* @param string $name
|
289 |
-
* @param mixed $variable
|
290 |
-
* @return $this
|
291 |
-
*/
|
292 |
-
public function set( $name, $variable ) {
|
293 |
-
// It is a function
|
294 |
-
if( is_callable( $variable ) )
|
295 |
-
$variable = $variable();
|
296 |
-
|
297 |
-
// Add it to services
|
298 |
-
$this->services[$name] = $variable;
|
299 |
-
|
300 |
-
return $this;
|
301 |
-
}
|
302 |
-
|
303 |
-
/**
|
304 |
-
* Get given name index from DI
|
305 |
-
* @param string $name
|
306 |
-
* @return mixed|null
|
307 |
-
*/
|
308 |
-
public function get( $name ) {
|
309 |
-
return (isset( $this->services[$name] )) ? $this->services[$name] : null;
|
310 |
-
}
|
311 |
-
|
312 |
-
/**
|
313 |
-
* @return string
|
314 |
-
*/
|
315 |
-
public function getVersion() {
|
316 |
-
return self::VERSION;
|
317 |
-
}
|
318 |
-
|
319 |
-
/**
|
320 |
-
* @return string
|
321 |
-
*/
|
322 |
-
public function getName() {
|
323 |
-
return self::NAME;
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* @return string
|
328 |
-
*/
|
329 |
-
public static function getSlug() {
|
330 |
-
return plugin_basename( dirname( dirname( dirname( __FILE__ ) ) ) );
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Get path to main plugin file
|
335 |
-
* @return string
|
336 |
-
*/
|
337 |
-
public function getPath() {
|
338 |
-
return dirname( dirname( __FILE__ ) );
|
339 |
-
}
|
340 |
-
|
341 |
-
/**
|
342 |
-
* Get main plugin url
|
343 |
-
* @return type
|
344 |
-
*/
|
345 |
-
public function getUrl() {
|
346 |
-
return plugin_dir_url( dirname( __FILE__ ) );
|
347 |
-
}
|
348 |
-
|
349 |
-
/**
|
350 |
-
* @return array|mixed|object
|
351 |
-
*/
|
352 |
-
public function getCPULoadSetting() {
|
353 |
-
$options = $this->get( "settings" );
|
354 |
-
$setting = $options->getCpuLoad();
|
355 |
-
|
356 |
-
switch ( $setting ) {
|
357 |
-
case "high":
|
358 |
-
$cpuLoad = 0;
|
359 |
-
break;
|
360 |
-
|
361 |
-
case "medium":
|
362 |
-
$cpuLoad = 1000;
|
363 |
-
break;
|
364 |
-
|
365 |
-
case "low":
|
366 |
-
$cpuLoad = 3000;
|
367 |
-
break;
|
368 |
-
|
369 |
-
case "default":
|
370 |
-
default:
|
371 |
-
$cpuLoad = 1000;
|
372 |
-
}
|
373 |
-
|
374 |
-
return $cpuLoad;
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
* Load language file
|
379 |
-
*/
|
380 |
-
public function loadLanguages() {
|
381 |
-
$languagesDirectory = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . self::SLUG . DIRECTORY_SEPARATOR;
|
382 |
-
$languagesDirectory.= "vars" . DIRECTORY_SEPARATOR . "languages" . DIRECTORY_SEPARATOR;
|
383 |
-
|
384 |
-
// Set filter for plugins languages directory
|
385 |
-
$languagesDirectory = apply_filters( "wpstg_languages_directory", $languagesDirectory );
|
386 |
-
|
387 |
-
// Traditional WP plugin locale filter
|
388 |
-
$locale = apply_filters( "plugin_locale", get_locale(), "wpstg" );
|
389 |
-
$moFile = sprintf( '%1$s-%2$s.mo', "wpstg", $locale );
|
390 |
-
|
391 |
-
// Setup paths to current locale file
|
392 |
-
$moFileLocal = $languagesDirectory . $moFile;
|
393 |
-
$moFileGlobal = WP_LANG_DIR . DIRECTORY_SEPARATOR . "wpstg" . DIRECTORY_SEPARATOR . $moFile;
|
394 |
-
|
395 |
-
// Global file (/wp-content/languages/WPSTG)
|
396 |
-
if( file_exists( $moFileGlobal ) ) {
|
397 |
-
load_textdomain( "wpstg", $moFileGlobal );
|
398 |
-
}
|
399 |
-
// Local file (/wp-content/plugins/wp-staging/languages/)
|
400 |
-
elseif( file_exists( $moFileLocal ) ) {
|
401 |
-
load_textdomain( "wpstg", $moFileGlobal );
|
402 |
-
}
|
403 |
-
// Default file
|
404 |
-
else {
|
405 |
-
load_plugin_textdomain( "wpstg", false, $languagesDirectory );
|
406 |
-
}
|
407 |
-
}
|
408 |
-
|
409 |
-
/**
|
410 |
-
* Check if it is a staging site
|
411 |
-
* @return bool
|
412 |
-
*/
|
413 |
-
private function isStagingSite() {
|
414 |
-
return ("true" === get_option( "wpstg_is_staging_site" ));
|
415 |
-
}
|
416 |
-
|
417 |
-
/**
|
418 |
-
* Initialize licensing functions
|
419 |
-
* @return boolean
|
420 |
-
*/
|
421 |
-
public function initLicensing() {
|
422 |
-
// Add licensing stuff if class exists
|
423 |
-
if( class_exists( 'WPStaging\Backend\Pro\Licensing\Licensing' ) ) {
|
424 |
-
$licensing = new Backend\Pro\Licensing\Licensing();
|
425 |
-
}
|
426 |
-
return false;
|
427 |
-
}
|
428 |
-
|
429 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging;
|
4 |
+
|
5 |
+
// No Direct Access
|
6 |
+
if( !defined( "WPINC" ) ) {
|
7 |
+
die;
|
8 |
+
}
|
9 |
+
|
10 |
+
// Ensure to include autoloader class
|
11 |
+
require_once __DIR__ . DIRECTORY_SEPARATOR . "Utils" . DIRECTORY_SEPARATOR . "Autoloader.php";
|
12 |
+
|
13 |
+
use WPStaging\Backend\Administrator;
|
14 |
+
use WPStaging\DTO\Settings;
|
15 |
+
use WPStaging\Frontend\Frontend;
|
16 |
+
use WPStaging\Utils\Autoloader;
|
17 |
+
use WPStaging\Utils\Cache;
|
18 |
+
use WPStaging\Utils\Loader;
|
19 |
+
use WPStaging\Utils\Logger;
|
20 |
+
use WPStaging\DI\InjectionAware;
|
21 |
+
use WPStaging\Cron\Cron;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Class WPStaging
|
25 |
+
* @package WPStaging
|
26 |
+
*/
|
27 |
+
final class WPStaging {
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Plugin version
|
31 |
+
*/
|
32 |
+
const VERSION = "2.1.9";
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Plugin name
|
36 |
+
*/
|
37 |
+
const NAME = "WP Staging";
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Plugin slug
|
41 |
+
*/
|
42 |
+
const SLUG = "wp-staging";
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Compatible WP Version
|
46 |
+
*/
|
47 |
+
const WP_COMPATIBLE = "4.9.4";
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Slug: Either wp-staging or wp-staging-pro
|
51 |
+
* @var string
|
52 |
+
*/
|
53 |
+
public $slug;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Absolute plugin path
|
57 |
+
* @var string
|
58 |
+
*/
|
59 |
+
public $pluginPath;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Services
|
63 |
+
* @var array
|
64 |
+
*/
|
65 |
+
private $services;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Singleton instance
|
69 |
+
* @var WPStaging
|
70 |
+
*/
|
71 |
+
private static $instance;
|
72 |
+
|
73 |
+
/**
|
74 |
+
* WPStaging constructor.
|
75 |
+
*/
|
76 |
+
private function __construct() {
|
77 |
+
|
78 |
+
$file = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . self::SLUG . DIRECTORY_SEPARATOR . self::SLUG . ".php";
|
79 |
+
|
80 |
+
$this->registerMain();
|
81 |
+
$this->registerNamespaces();
|
82 |
+
$this->loadLanguages();
|
83 |
+
$this->loadDependencies();
|
84 |
+
$this->defineHooks();
|
85 |
+
// Licensing stuff be loaded in wpstg core to make cron hook available from frontpage
|
86 |
+
$this->initLicensing();
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Method to be executed upon activation of the plugin
|
91 |
+
*/
|
92 |
+
public function onActivation() {
|
93 |
+
$Activation = new \WPStaging\Backend\Activation\Activation();
|
94 |
+
$Activation->install_dependancies();
|
95 |
+
}
|
96 |
+
|
97 |
+
public function registerMain() {
|
98 |
+
// Slug of the plugin
|
99 |
+
$this->slug = plugin_basename( dirname( dirname( dirname( __FILE__ ) ) ) );
|
100 |
+
|
101 |
+
// absolute path to the main plugin dir
|
102 |
+
$this->pluginPath = plugin_dir_path( dirname( dirname( __FILE__ ) ) );
|
103 |
+
|
104 |
+
// URL to apps folder
|
105 |
+
$this->url = plugin_dir_url( dirname( __FILE__ ) );
|
106 |
+
|
107 |
+
// URL to backend public folder folder
|
108 |
+
$this->backend_url = plugin_dir_url( dirname( __FILE__ ) ) . "Backend/public/";
|
109 |
+
|
110 |
+
// URL to frontend public folder folder
|
111 |
+
$this->frontend_url = plugin_dir_url( dirname( __FILE__ ) ) . "Frontend/public/";
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Define Hooks
|
116 |
+
*/
|
117 |
+
public function defineHooks() {
|
118 |
+
$loader = $this->get( "loader" );
|
119 |
+
$loader->addAction( "admin_enqueue_scripts", $this, "enqueueElements", 100 );
|
120 |
+
$loader->addAction( "wp_enqueue_scripts", $this, "enqueueElements", 100 );
|
121 |
+
$this->addIntervals();
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Add new cron time event "weekly"
|
126 |
+
*/
|
127 |
+
public function addIntervals(){
|
128 |
+
$interval = new Cron();
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Scripts and Styles
|
133 |
+
* @param string $hook
|
134 |
+
*/
|
135 |
+
public function enqueueElements( $hook ) {
|
136 |
+
|
137 |
+
// Load this css file on frontend and backend on all pages if current site is a staging site
|
138 |
+
if( $this->isStagingSite() ) {
|
139 |
+
wp_enqueue_style( "wpstg-admin-bar", $this->backend_url . "css/wpstg-admin-bar.css", $this->getVersion() );
|
140 |
+
}
|
141 |
+
|
142 |
+
$availablePages = array(
|
143 |
+
"toplevel_page_wpstg_clone",
|
144 |
+
"wp-staging_page_wpstg-settings",
|
145 |
+
"wp-staging_page_wpstg-tools",
|
146 |
+
"wp-staging_page_wpstg-license",
|
147 |
+
"wp-staging_page_wpstg-welcome",
|
148 |
+
);
|
149 |
+
|
150 |
+
// Load these css and js files only on wp staging admin pages
|
151 |
+
if( !in_array( $hook, $availablePages ) || !is_admin() ) {
|
152 |
+
return;
|
153 |
+
}
|
154 |
+
|
155 |
+
// Load admin js files
|
156 |
+
wp_enqueue_script(
|
157 |
+
"wpstg-admin-script", $this->backend_url . "js/wpstg-admin.js", array("jquery"), $this->getVersion(), false
|
158 |
+
);
|
159 |
+
|
160 |
+
// Load admin css files
|
161 |
+
wp_enqueue_style(
|
162 |
+
"wpstg-admin", $this->backend_url . "css/wpstg-admin.css", $this->getVersion()
|
163 |
+
);
|
164 |
+
|
165 |
+
wp_localize_script( "wpstg-admin-script", "wpstg", array(
|
166 |
+
"nonce" => wp_create_nonce( "wpstg_ajax_nonce" ),
|
167 |
+
"mu_plugin_confirmation" => __(
|
168 |
+
"If confirmed we will install an additional WordPress 'Must Use' plugin. "
|
169 |
+
. "This plugin will allow us to control which plugins are loaded during "
|
170 |
+
. "WP Staging specific operations. Do you wish to continue?", "wpstg"
|
171 |
+
),
|
172 |
+
"plugin_compatibility_settings_problem" => __(
|
173 |
+
"A problem occurred when trying to change the plugin compatibility setting.", "wpstg"
|
174 |
+
),
|
175 |
+
"saved" => __( "Saved", "The settings were saved successfully", "wpstg" ),
|
176 |
+
"status" => __( "Status", "Current request status", "wpstg" ),
|
177 |
+
"response" => __( "Response", "The message the server responded with", "wpstg" ),
|
178 |
+
"blacklist_problem" => __(
|
179 |
+
"A problem occurred when trying to add plugins to backlist.", "wpstg"
|
180 |
+
),
|
181 |
+
"cpuLoad" => $this->getCPULoadSetting(),
|
182 |
+
"settings" => ( object ) array(), // TODO add settings?
|
183 |
+
"tblprefix" => self::getTablePrefix()
|
184 |
+
) );
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Get table prefix of the current site
|
189 |
+
* @return string
|
190 |
+
*/
|
191 |
+
public static function getTablePrefix(){
|
192 |
+
$wpDB = WPStaging::getInstance()->get("wpdb");
|
193 |
+
return $wpDB->prefix;
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Caching and logging folder
|
198 |
+
*
|
199 |
+
* @return string
|
200 |
+
*/
|
201 |
+
public static function getContentDir() {
|
202 |
+
$wp_upload_dir = wp_upload_dir();
|
203 |
+
$path = $wp_upload_dir['basedir'] . '/wp-staging';
|
204 |
+
wp_mkdir_p( $path );
|
205 |
+
return apply_filters( 'wpstg_get_upload_dir', $path . DIRECTORY_SEPARATOR );
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Register used namespaces
|
210 |
+
*/
|
211 |
+
private function registerNamespaces() {
|
212 |
+
$autoloader = new Autoloader();
|
213 |
+
$this->set( "autoloader", $autoloader );
|
214 |
+
|
215 |
+
// Autoloader
|
216 |
+
$autoloader->registerNamespaces( array(
|
217 |
+
"WPStaging" => array(
|
218 |
+
$this->pluginPath . 'apps' . DIRECTORY_SEPARATOR,
|
219 |
+
$this->pluginPath . 'apps' . DIRECTORY_SEPARATOR . 'Core' . DIRECTORY_SEPARATOR,
|
220 |
+
)
|
221 |
+
) );
|
222 |
+
|
223 |
+
// Register namespaces
|
224 |
+
$autoloader->register();
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Get Instance
|
229 |
+
* @return WPStaging
|
230 |
+
*/
|
231 |
+
public static function getInstance() {
|
232 |
+
if( null === static::$instance ) {
|
233 |
+
static::$instance = new static();
|
234 |
+
}
|
235 |
+
|
236 |
+
return static::$instance;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Prevent cloning
|
241 |
+
* @return void
|
242 |
+
*/
|
243 |
+
private function __clone() {
|
244 |
+
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Prevent unserialization
|
249 |
+
* @return void
|
250 |
+
*/
|
251 |
+
private function __wakeup() {
|
252 |
+
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Load Dependencies
|
257 |
+
*/
|
258 |
+
private function loadDependencies() {
|
259 |
+
// Set loader
|
260 |
+
$this->set( "loader", new Loader() );
|
261 |
+
|
262 |
+
// Set cache
|
263 |
+
$this->set( "cache", new Cache() );
|
264 |
+
|
265 |
+
// Set logger
|
266 |
+
$this->set( "logger", new Logger() );
|
267 |
+
|
268 |
+
// Set settings
|
269 |
+
$this->set( "settings", new Settings() );
|
270 |
+
|
271 |
+
// Set Administrator
|
272 |
+
if( is_admin() ) {
|
273 |
+
new Administrator( $this );
|
274 |
+
} else {
|
275 |
+
new Frontend( $this );
|
276 |
+
}
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Execute Plugin
|
281 |
+
*/
|
282 |
+
public function run() {
|
283 |
+
$this->get( "loader" )->run();
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Set a variable to DI with given name
|
288 |
+
* @param string $name
|
289 |
+
* @param mixed $variable
|
290 |
+
* @return $this
|
291 |
+
*/
|
292 |
+
public function set( $name, $variable ) {
|
293 |
+
// It is a function
|
294 |
+
if( is_callable( $variable ) )
|
295 |
+
$variable = $variable();
|
296 |
+
|
297 |
+
// Add it to services
|
298 |
+
$this->services[$name] = $variable;
|
299 |
+
|
300 |
+
return $this;
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Get given name index from DI
|
305 |
+
* @param string $name
|
306 |
+
* @return mixed|null
|
307 |
+
*/
|
308 |
+
public function get( $name ) {
|
309 |
+
return (isset( $this->services[$name] )) ? $this->services[$name] : null;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @return string
|
314 |
+
*/
|
315 |
+
public function getVersion() {
|
316 |
+
return self::VERSION;
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* @return string
|
321 |
+
*/
|
322 |
+
public function getName() {
|
323 |
+
return self::NAME;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* @return string
|
328 |
+
*/
|
329 |
+
public static function getSlug() {
|
330 |
+
return plugin_basename( dirname( dirname( dirname( __FILE__ ) ) ) );
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Get path to main plugin file
|
335 |
+
* @return string
|
336 |
+
*/
|
337 |
+
public function getPath() {
|
338 |
+
return dirname( dirname( __FILE__ ) );
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Get main plugin url
|
343 |
+
* @return type
|
344 |
+
*/
|
345 |
+
public function getUrl() {
|
346 |
+
return plugin_dir_url( dirname( __FILE__ ) );
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* @return array|mixed|object
|
351 |
+
*/
|
352 |
+
public function getCPULoadSetting() {
|
353 |
+
$options = $this->get( "settings" );
|
354 |
+
$setting = $options->getCpuLoad();
|
355 |
+
|
356 |
+
switch ( $setting ) {
|
357 |
+
case "high":
|
358 |
+
$cpuLoad = 0;
|
359 |
+
break;
|
360 |
+
|
361 |
+
case "medium":
|
362 |
+
$cpuLoad = 1000;
|
363 |
+
break;
|
364 |
+
|
365 |
+
case "low":
|
366 |
+
$cpuLoad = 3000;
|
367 |
+
break;
|
368 |
+
|
369 |
+
case "default":
|
370 |
+
default:
|
371 |
+
$cpuLoad = 1000;
|
372 |
+
}
|
373 |
+
|
374 |
+
return $cpuLoad;
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Load language file
|
379 |
+
*/
|
380 |
+
public function loadLanguages() {
|
381 |
+
$languagesDirectory = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . self::SLUG . DIRECTORY_SEPARATOR;
|
382 |
+
$languagesDirectory.= "vars" . DIRECTORY_SEPARATOR . "languages" . DIRECTORY_SEPARATOR;
|
383 |
+
|
384 |
+
// Set filter for plugins languages directory
|
385 |
+
$languagesDirectory = apply_filters( "wpstg_languages_directory", $languagesDirectory );
|
386 |
+
|
387 |
+
// Traditional WP plugin locale filter
|
388 |
+
$locale = apply_filters( "plugin_locale", get_locale(), "wpstg" );
|
389 |
+
$moFile = sprintf( '%1$s-%2$s.mo', "wpstg", $locale );
|
390 |
+
|
391 |
+
// Setup paths to current locale file
|
392 |
+
$moFileLocal = $languagesDirectory . $moFile;
|
393 |
+
$moFileGlobal = WP_LANG_DIR . DIRECTORY_SEPARATOR . "wpstg" . DIRECTORY_SEPARATOR . $moFile;
|
394 |
+
|
395 |
+
// Global file (/wp-content/languages/WPSTG)
|
396 |
+
if( file_exists( $moFileGlobal ) ) {
|
397 |
+
load_textdomain( "wpstg", $moFileGlobal );
|
398 |
+
}
|
399 |
+
// Local file (/wp-content/plugins/wp-staging/languages/)
|
400 |
+
elseif( file_exists( $moFileLocal ) ) {
|
401 |
+
load_textdomain( "wpstg", $moFileGlobal );
|
402 |
+
}
|
403 |
+
// Default file
|
404 |
+
else {
|
405 |
+
load_plugin_textdomain( "wpstg", false, $languagesDirectory );
|
406 |
+
}
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Check if it is a staging site
|
411 |
+
* @return bool
|
412 |
+
*/
|
413 |
+
private function isStagingSite() {
|
414 |
+
return ("true" === get_option( "wpstg_is_staging_site" ));
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Initialize licensing functions
|
419 |
+
* @return boolean
|
420 |
+
*/
|
421 |
+
public function initLicensing() {
|
422 |
+
// Add licensing stuff if class exists
|
423 |
+
if( class_exists( 'WPStaging\Backend\Pro\Licensing\Licensing' ) ) {
|
424 |
+
$licensing = new Backend\Pro\Licensing\Licensing();
|
425 |
+
}
|
426 |
+
return false;
|
427 |
+
}
|
428 |
+
|
429 |
+
}
|
package-lock.json
DELETED
@@ -1,3333 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"name": "wp-staging",
|
3 |
-
"version": "2.1.6",
|
4 |
-
"lockfileVersion": 1,
|
5 |
-
"requires": true,
|
6 |
-
"dependencies": {
|
7 |
-
"abbrev": {
|
8 |
-
"version": "1.1.1",
|
9 |
-
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
10 |
-
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
11 |
-
"dev": true
|
12 |
-
},
|
13 |
-
"ajv": {
|
14 |
-
"version": "5.5.1",
|
15 |
-
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz",
|
16 |
-
"integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=",
|
17 |
-
"dev": true,
|
18 |
-
"optional": true,
|
19 |
-
"requires": {
|
20 |
-
"co": "4.6.0",
|
21 |
-
"fast-deep-equal": "1.0.0",
|
22 |
-
"fast-json-stable-stringify": "2.0.0",
|
23 |
-
"json-schema-traverse": "0.3.1"
|
24 |
-
}
|
25 |
-
},
|
26 |
-
"amdefine": {
|
27 |
-
"version": "1.0.1",
|
28 |
-
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
29 |
-
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
|
30 |
-
"dev": true
|
31 |
-
},
|
32 |
-
"ansi-regex": {
|
33 |
-
"version": "0.2.1",
|
34 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
|
35 |
-
"integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
|
36 |
-
"dev": true
|
37 |
-
},
|
38 |
-
"ansi-styles": {
|
39 |
-
"version": "1.1.0",
|
40 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
|
41 |
-
"integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
|
42 |
-
"dev": true
|
43 |
-
},
|
44 |
-
"aproba": {
|
45 |
-
"version": "1.2.0",
|
46 |
-
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
47 |
-
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
|
48 |
-
"dev": true
|
49 |
-
},
|
50 |
-
"archiver": {
|
51 |
-
"version": "1.3.0",
|
52 |
-
"resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz",
|
53 |
-
"integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=",
|
54 |
-
"dev": true,
|
55 |
-
"requires": {
|
56 |
-
"archiver-utils": "1.3.0",
|
57 |
-
"async": "2.6.0",
|
58 |
-
"buffer-crc32": "0.2.13",
|
59 |
-
"glob": "7.1.2",
|
60 |
-
"lodash": "4.17.4",
|
61 |
-
"readable-stream": "2.3.3",
|
62 |
-
"tar-stream": "1.5.5",
|
63 |
-
"walkdir": "0.0.11",
|
64 |
-
"zip-stream": "1.2.0"
|
65 |
-
},
|
66 |
-
"dependencies": {
|
67 |
-
"async": {
|
68 |
-
"version": "2.6.0",
|
69 |
-
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
|
70 |
-
"integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
|
71 |
-
"dev": true,
|
72 |
-
"requires": {
|
73 |
-
"lodash": "4.17.4"
|
74 |
-
}
|
75 |
-
},
|
76 |
-
"glob": {
|
77 |
-
"version": "7.1.2",
|
78 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
79 |
-
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
80 |
-
"dev": true,
|
81 |
-
"requires": {
|
82 |
-
"fs.realpath": "1.0.0",
|
83 |
-
"inflight": "1.0.6",
|
84 |
-
"inherits": "2.0.3",
|
85 |
-
"minimatch": "3.0.4",
|
86 |
-
"once": "1.4.0",
|
87 |
-
"path-is-absolute": "1.0.1"
|
88 |
-
}
|
89 |
-
},
|
90 |
-
"lodash": {
|
91 |
-
"version": "4.17.4",
|
92 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
93 |
-
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
94 |
-
"dev": true
|
95 |
-
},
|
96 |
-
"minimatch": {
|
97 |
-
"version": "3.0.4",
|
98 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
99 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
100 |
-
"dev": true,
|
101 |
-
"requires": {
|
102 |
-
"brace-expansion": "1.1.8"
|
103 |
-
}
|
104 |
-
}
|
105 |
-
}
|
106 |
-
},
|
107 |
-
"archiver-utils": {
|
108 |
-
"version": "1.3.0",
|
109 |
-
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz",
|
110 |
-
"integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=",
|
111 |
-
"dev": true,
|
112 |
-
"requires": {
|
113 |
-
"glob": "7.1.2",
|
114 |
-
"graceful-fs": "4.1.11",
|
115 |
-
"lazystream": "1.0.0",
|
116 |
-
"lodash": "4.17.4",
|
117 |
-
"normalize-path": "2.1.1",
|
118 |
-
"readable-stream": "2.3.3"
|
119 |
-
},
|
120 |
-
"dependencies": {
|
121 |
-
"glob": {
|
122 |
-
"version": "7.1.2",
|
123 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
124 |
-
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
125 |
-
"dev": true,
|
126 |
-
"requires": {
|
127 |
-
"fs.realpath": "1.0.0",
|
128 |
-
"inflight": "1.0.6",
|
129 |
-
"inherits": "2.0.3",
|
130 |
-
"minimatch": "3.0.4",
|
131 |
-
"once": "1.4.0",
|
132 |
-
"path-is-absolute": "1.0.1"
|
133 |
-
}
|
134 |
-
},
|
135 |
-
"graceful-fs": {
|
136 |
-
"version": "4.1.11",
|
137 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
138 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
139 |
-
"dev": true
|
140 |
-
},
|
141 |
-
"lodash": {
|
142 |
-
"version": "4.17.4",
|
143 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
144 |
-
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
145 |
-
"dev": true
|
146 |
-
},
|
147 |
-
"minimatch": {
|
148 |
-
"version": "3.0.4",
|
149 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
150 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
151 |
-
"dev": true,
|
152 |
-
"requires": {
|
153 |
-
"brace-expansion": "1.1.8"
|
154 |
-
}
|
155 |
-
}
|
156 |
-
}
|
157 |
-
},
|
158 |
-
"are-we-there-yet": {
|
159 |
-
"version": "1.1.4",
|
160 |
-
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
|
161 |
-
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
|
162 |
-
"dev": true,
|
163 |
-
"requires": {
|
164 |
-
"delegates": "1.0.0",
|
165 |
-
"readable-stream": "2.3.3"
|
166 |
-
}
|
167 |
-
},
|
168 |
-
"argparse": {
|
169 |
-
"version": "1.0.9",
|
170 |
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
|
171 |
-
"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
|
172 |
-
"dev": true,
|
173 |
-
"requires": {
|
174 |
-
"sprintf-js": "1.0.3"
|
175 |
-
}
|
176 |
-
},
|
177 |
-
"array-differ": {
|
178 |
-
"version": "1.0.0",
|
179 |
-
"resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
|
180 |
-
"integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
|
181 |
-
"dev": true
|
182 |
-
},
|
183 |
-
"array-find-index": {
|
184 |
-
"version": "1.0.2",
|
185 |
-
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
186 |
-
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
|
187 |
-
"dev": true
|
188 |
-
},
|
189 |
-
"array-union": {
|
190 |
-
"version": "1.0.2",
|
191 |
-
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
192 |
-
"integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
|
193 |
-
"dev": true,
|
194 |
-
"requires": {
|
195 |
-
"array-uniq": "1.0.3"
|
196 |
-
}
|
197 |
-
},
|
198 |
-
"array-uniq": {
|
199 |
-
"version": "1.0.3",
|
200 |
-
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
|
201 |
-
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
|
202 |
-
"dev": true
|
203 |
-
},
|
204 |
-
"arrify": {
|
205 |
-
"version": "1.0.1",
|
206 |
-
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
|
207 |
-
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
|
208 |
-
"dev": true
|
209 |
-
},
|
210 |
-
"asn1": {
|
211 |
-
"version": "0.2.3",
|
212 |
-
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
213 |
-
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
|
214 |
-
"dev": true,
|
215 |
-
"optional": true
|
216 |
-
},
|
217 |
-
"assert-plus": {
|
218 |
-
"version": "1.0.0",
|
219 |
-
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
220 |
-
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
221 |
-
"dev": true
|
222 |
-
},
|
223 |
-
"async": {
|
224 |
-
"version": "1.5.2",
|
225 |
-
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
226 |
-
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
227 |
-
"dev": true
|
228 |
-
},
|
229 |
-
"asynckit": {
|
230 |
-
"version": "0.4.0",
|
231 |
-
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
232 |
-
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
233 |
-
"dev": true,
|
234 |
-
"optional": true
|
235 |
-
},
|
236 |
-
"aws-sign2": {
|
237 |
-
"version": "0.7.0",
|
238 |
-
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
239 |
-
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
240 |
-
"dev": true,
|
241 |
-
"optional": true
|
242 |
-
},
|
243 |
-
"aws4": {
|
244 |
-
"version": "1.6.0",
|
245 |
-
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
|
246 |
-
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
|
247 |
-
"dev": true,
|
248 |
-
"optional": true
|
249 |
-
},
|
250 |
-
"balanced-match": {
|
251 |
-
"version": "1.0.0",
|
252 |
-
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
253 |
-
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
254 |
-
"dev": true
|
255 |
-
},
|
256 |
-
"bcrypt-pbkdf": {
|
257 |
-
"version": "1.0.1",
|
258 |
-
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
259 |
-
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
260 |
-
"dev": true,
|
261 |
-
"optional": true,
|
262 |
-
"requires": {
|
263 |
-
"tweetnacl": "0.14.5"
|
264 |
-
}
|
265 |
-
},
|
266 |
-
"bl": {
|
267 |
-
"version": "1.2.1",
|
268 |
-
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz",
|
269 |
-
"integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=",
|
270 |
-
"dev": true,
|
271 |
-
"requires": {
|
272 |
-
"readable-stream": "2.3.3"
|
273 |
-
}
|
274 |
-
},
|
275 |
-
"block-stream": {
|
276 |
-
"version": "0.0.9",
|
277 |
-
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
278 |
-
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
|
279 |
-
"dev": true,
|
280 |
-
"optional": true,
|
281 |
-
"requires": {
|
282 |
-
"inherits": "2.0.3"
|
283 |
-
}
|
284 |
-
},
|
285 |
-
"boom": {
|
286 |
-
"version": "4.3.1",
|
287 |
-
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
|
288 |
-
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
|
289 |
-
"dev": true,
|
290 |
-
"optional": true,
|
291 |
-
"requires": {
|
292 |
-
"hoek": "4.2.0"
|
293 |
-
}
|
294 |
-
},
|
295 |
-
"brace-expansion": {
|
296 |
-
"version": "1.1.8",
|
297 |
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
298 |
-
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
299 |
-
"dev": true,
|
300 |
-
"requires": {
|
301 |
-
"balanced-match": "1.0.0",
|
302 |
-
"concat-map": "0.0.1"
|
303 |
-
}
|
304 |
-
},
|
305 |
-
"browserify-zlib": {
|
306 |
-
"version": "0.1.4",
|
307 |
-
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
|
308 |
-
"integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
|
309 |
-
"dev": true,
|
310 |
-
"requires": {
|
311 |
-
"pako": "0.2.9"
|
312 |
-
}
|
313 |
-
},
|
314 |
-
"buffer-crc32": {
|
315 |
-
"version": "0.2.13",
|
316 |
-
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
317 |
-
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
|
318 |
-
"dev": true
|
319 |
-
},
|
320 |
-
"builtin-modules": {
|
321 |
-
"version": "1.1.1",
|
322 |
-
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
323 |
-
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
324 |
-
"dev": true
|
325 |
-
},
|
326 |
-
"cache-swap": {
|
327 |
-
"version": "0.0.6",
|
328 |
-
"resolved": "https://registry.npmjs.org/cache-swap/-/cache-swap-0.0.6.tgz",
|
329 |
-
"integrity": "sha1-F834NebDAf0VgJCwPRzDb0Z7FpU=",
|
330 |
-
"dev": true,
|
331 |
-
"requires": {
|
332 |
-
"async": "0.2.10",
|
333 |
-
"lodash": "1.1.1",
|
334 |
-
"rimraf": "2.1.4"
|
335 |
-
},
|
336 |
-
"dependencies": {
|
337 |
-
"async": {
|
338 |
-
"version": "0.2.10",
|
339 |
-
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
340 |
-
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
|
341 |
-
"dev": true
|
342 |
-
},
|
343 |
-
"lodash": {
|
344 |
-
"version": "1.1.1",
|
345 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-1.1.1.tgz",
|
346 |
-
"integrity": "sha1-QaKy6aAOZNbRmZ8UP/awdV9ruyQ=",
|
347 |
-
"dev": true
|
348 |
-
},
|
349 |
-
"rimraf": {
|
350 |
-
"version": "2.1.4",
|
351 |
-
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.1.4.tgz",
|
352 |
-
"integrity": "sha1-Wm62Lu2gaPUe3lDymz5c0i89m7I=",
|
353 |
-
"dev": true,
|
354 |
-
"requires": {
|
355 |
-
"graceful-fs": "1.2.3"
|
356 |
-
}
|
357 |
-
}
|
358 |
-
}
|
359 |
-
},
|
360 |
-
"camelcase": {
|
361 |
-
"version": "2.1.1",
|
362 |
-
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
|
363 |
-
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
|
364 |
-
"dev": true
|
365 |
-
},
|
366 |
-
"camelcase-keys": {
|
367 |
-
"version": "2.1.0",
|
368 |
-
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
|
369 |
-
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
|
370 |
-
"dev": true,
|
371 |
-
"requires": {
|
372 |
-
"camelcase": "2.1.1",
|
373 |
-
"map-obj": "1.0.1"
|
374 |
-
}
|
375 |
-
},
|
376 |
-
"caseless": {
|
377 |
-
"version": "0.12.0",
|
378 |
-
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
379 |
-
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
380 |
-
"dev": true,
|
381 |
-
"optional": true
|
382 |
-
},
|
383 |
-
"chalk": {
|
384 |
-
"version": "0.5.1",
|
385 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
|
386 |
-
"integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
|
387 |
-
"dev": true,
|
388 |
-
"requires": {
|
389 |
-
"ansi-styles": "1.1.0",
|
390 |
-
"escape-string-regexp": "1.0.5",
|
391 |
-
"has-ansi": "0.1.0",
|
392 |
-
"strip-ansi": "0.3.0",
|
393 |
-
"supports-color": "0.2.0"
|
394 |
-
}
|
395 |
-
},
|
396 |
-
"chownr": {
|
397 |
-
"version": "1.0.1",
|
398 |
-
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
|
399 |
-
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
|
400 |
-
"dev": true,
|
401 |
-
"optional": true
|
402 |
-
},
|
403 |
-
"clean-css": {
|
404 |
-
"version": "3.4.28",
|
405 |
-
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
|
406 |
-
"integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
|
407 |
-
"dev": true,
|
408 |
-
"requires": {
|
409 |
-
"commander": "2.8.1",
|
410 |
-
"source-map": "0.4.4"
|
411 |
-
}
|
412 |
-
},
|
413 |
-
"cli": {
|
414 |
-
"version": "0.4.5",
|
415 |
-
"resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz",
|
416 |
-
"integrity": "sha1-ePlIXNFhtWbppsctcXDEJw6B22E=",
|
417 |
-
"dev": true,
|
418 |
-
"requires": {
|
419 |
-
"glob": "3.1.21"
|
420 |
-
}
|
421 |
-
},
|
422 |
-
"co": {
|
423 |
-
"version": "4.6.0",
|
424 |
-
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
425 |
-
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
|
426 |
-
"dev": true,
|
427 |
-
"optional": true
|
428 |
-
},
|
429 |
-
"code-point-at": {
|
430 |
-
"version": "1.1.0",
|
431 |
-
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
432 |
-
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
433 |
-
"dev": true
|
434 |
-
},
|
435 |
-
"coffee-script": {
|
436 |
-
"version": "1.10.0",
|
437 |
-
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
|
438 |
-
"integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=",
|
439 |
-
"dev": true
|
440 |
-
},
|
441 |
-
"colors": {
|
442 |
-
"version": "1.1.2",
|
443 |
-
"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
|
444 |
-
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
|
445 |
-
"dev": true
|
446 |
-
},
|
447 |
-
"combined-stream": {
|
448 |
-
"version": "1.0.5",
|
449 |
-
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
|
450 |
-
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
|
451 |
-
"dev": true,
|
452 |
-
"requires": {
|
453 |
-
"delayed-stream": "1.0.0"
|
454 |
-
}
|
455 |
-
},
|
456 |
-
"commander": {
|
457 |
-
"version": "2.8.1",
|
458 |
-
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
459 |
-
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
460 |
-
"dev": true,
|
461 |
-
"requires": {
|
462 |
-
"graceful-readlink": "1.0.1"
|
463 |
-
}
|
464 |
-
},
|
465 |
-
"compress-commons": {
|
466 |
-
"version": "1.2.2",
|
467 |
-
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz",
|
468 |
-
"integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=",
|
469 |
-
"dev": true,
|
470 |
-
"requires": {
|
471 |
-
"buffer-crc32": "0.2.13",
|
472 |
-
"crc32-stream": "2.0.0",
|
473 |
-
"normalize-path": "2.1.1",
|
474 |
-
"readable-stream": "2.3.3"
|
475 |
-
}
|
476 |
-
},
|
477 |
-
"concat-map": {
|
478 |
-
"version": "0.0.1",
|
479 |
-
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
480 |
-
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
481 |
-
"dev": true
|
482 |
-
},
|
483 |
-
"concat-stream": {
|
484 |
-
"version": "1.6.0",
|
485 |
-
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
|
486 |
-
"integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
|
487 |
-
"dev": true,
|
488 |
-
"requires": {
|
489 |
-
"inherits": "2.0.3",
|
490 |
-
"readable-stream": "2.3.3",
|
491 |
-
"typedarray": "0.0.6"
|
492 |
-
},
|
493 |
-
"dependencies": {
|
494 |
-
"isarray": {
|
495 |
-
"version": "1.0.0",
|
496 |
-
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
497 |
-
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
498 |
-
"dev": true
|
499 |
-
},
|
500 |
-
"readable-stream": {
|
501 |
-
"version": "2.3.3",
|
502 |
-
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
503 |
-
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
|
504 |
-
"dev": true,
|
505 |
-
"requires": {
|
506 |
-
"core-util-is": "1.0.2",
|
507 |
-
"inherits": "2.0.3",
|
508 |
-
"isarray": "1.0.0",
|
509 |
-
"process-nextick-args": "1.0.7",
|
510 |
-
"safe-buffer": "5.1.1",
|
511 |
-
"string_decoder": "1.0.3",
|
512 |
-
"util-deprecate": "1.0.2"
|
513 |
-
}
|
514 |
-
},
|
515 |
-
"string_decoder": {
|
516 |
-
"version": "1.0.3",
|
517 |
-
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
518 |
-
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
519 |
-
"dev": true,
|
520 |
-
"requires": {
|
521 |
-
"safe-buffer": "5.1.1"
|
522 |
-
}
|
523 |
-
}
|
524 |
-
}
|
525 |
-
},
|
526 |
-
"console-browserify": {
|
527 |
-
"version": "0.1.6",
|
528 |
-
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz",
|
529 |
-
"integrity": "sha1-0SijwLuINQ61YmxufHGm8P1ImDw=",
|
530 |
-
"dev": true
|
531 |
-
},
|
532 |
-
"console-control-strings": {
|
533 |
-
"version": "1.1.0",
|
534 |
-
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
535 |
-
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
536 |
-
"dev": true
|
537 |
-
},
|
538 |
-
"core-util-is": {
|
539 |
-
"version": "1.0.2",
|
540 |
-
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
541 |
-
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
542 |
-
"dev": true
|
543 |
-
},
|
544 |
-
"crc": {
|
545 |
-
"version": "3.5.0",
|
546 |
-
"resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz",
|
547 |
-
"integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=",
|
548 |
-
"dev": true
|
549 |
-
},
|
550 |
-
"crc32-stream": {
|
551 |
-
"version": "2.0.0",
|
552 |
-
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz",
|
553 |
-
"integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=",
|
554 |
-
"dev": true,
|
555 |
-
"requires": {
|
556 |
-
"crc": "3.5.0",
|
557 |
-
"readable-stream": "2.3.3"
|
558 |
-
}
|
559 |
-
},
|
560 |
-
"cryptiles": {
|
561 |
-
"version": "3.1.2",
|
562 |
-
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
|
563 |
-
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
|
564 |
-
"dev": true,
|
565 |
-
"optional": true,
|
566 |
-
"requires": {
|
567 |
-
"boom": "5.2.0"
|
568 |
-
},
|
569 |
-
"dependencies": {
|
570 |
-
"boom": {
|
571 |
-
"version": "5.2.0",
|
572 |
-
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
573 |
-
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
574 |
-
"dev": true,
|
575 |
-
"optional": true,
|
576 |
-
"requires": {
|
577 |
-
"hoek": "4.2.0"
|
578 |
-
}
|
579 |
-
}
|
580 |
-
}
|
581 |
-
},
|
582 |
-
"cson": {
|
583 |
-
"version": "3.0.2",
|
584 |
-
"resolved": "https://registry.npmjs.org/cson/-/cson-3.0.2.tgz",
|
585 |
-
"integrity": "sha1-g+6Qids8JUvsHpjkmNmqzxGtzFQ=",
|
586 |
-
"dev": true,
|
587 |
-
"requires": {
|
588 |
-
"coffee-script": "1.12.7",
|
589 |
-
"cson-parser": "1.3.5",
|
590 |
-
"extract-opts": "3.3.1",
|
591 |
-
"requirefresh": "2.1.0",
|
592 |
-
"safefs": "4.1.0"
|
593 |
-
},
|
594 |
-
"dependencies": {
|
595 |
-
"coffee-script": {
|
596 |
-
"version": "1.12.7",
|
597 |
-
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
598 |
-
"integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==",
|
599 |
-
"dev": true
|
600 |
-
}
|
601 |
-
}
|
602 |
-
},
|
603 |
-
"cson-parser": {
|
604 |
-
"version": "1.3.5",
|
605 |
-
"resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.3.5.tgz",
|
606 |
-
"integrity": "sha1-fsZ14DkUVTO/KmqFYHPxWZ2cLSQ=",
|
607 |
-
"dev": true,
|
608 |
-
"requires": {
|
609 |
-
"coffee-script": "1.12.7"
|
610 |
-
},
|
611 |
-
"dependencies": {
|
612 |
-
"coffee-script": {
|
613 |
-
"version": "1.12.7",
|
614 |
-
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
615 |
-
"integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==",
|
616 |
-
"dev": true
|
617 |
-
}
|
618 |
-
}
|
619 |
-
},
|
620 |
-
"currently-unhandled": {
|
621 |
-
"version": "0.4.1",
|
622 |
-
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
|
623 |
-
"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
|
624 |
-
"dev": true,
|
625 |
-
"requires": {
|
626 |
-
"array-find-index": "1.0.2"
|
627 |
-
}
|
628 |
-
},
|
629 |
-
"dashdash": {
|
630 |
-
"version": "1.14.1",
|
631 |
-
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
632 |
-
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
633 |
-
"dev": true,
|
634 |
-
"optional": true,
|
635 |
-
"requires": {
|
636 |
-
"assert-plus": "1.0.0"
|
637 |
-
}
|
638 |
-
},
|
639 |
-
"date-time": {
|
640 |
-
"version": "1.1.0",
|
641 |
-
"resolved": "https://registry.npmjs.org/date-time/-/date-time-1.1.0.tgz",
|
642 |
-
"integrity": "sha1-GIdtC9pMGf5w3Tv0sDTygbEqQLY=",
|
643 |
-
"dev": true,
|
644 |
-
"requires": {
|
645 |
-
"time-zone": "0.1.0"
|
646 |
-
}
|
647 |
-
},
|
648 |
-
"dateformat": {
|
649 |
-
"version": "1.0.12",
|
650 |
-
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
|
651 |
-
"integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
|
652 |
-
"dev": true,
|
653 |
-
"requires": {
|
654 |
-
"get-stdin": "4.0.1",
|
655 |
-
"meow": "3.7.0"
|
656 |
-
}
|
657 |
-
},
|
658 |
-
"decamelize": {
|
659 |
-
"version": "1.2.0",
|
660 |
-
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
661 |
-
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
662 |
-
"dev": true
|
663 |
-
},
|
664 |
-
"deep-extend": {
|
665 |
-
"version": "0.4.2",
|
666 |
-
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
|
667 |
-
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
|
668 |
-
"dev": true,
|
669 |
-
"optional": true
|
670 |
-
},
|
671 |
-
"delayed-stream": {
|
672 |
-
"version": "1.0.0",
|
673 |
-
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
674 |
-
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
675 |
-
"dev": true
|
676 |
-
},
|
677 |
-
"delegates": {
|
678 |
-
"version": "1.0.0",
|
679 |
-
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
680 |
-
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
681 |
-
"dev": true
|
682 |
-
},
|
683 |
-
"detect-libc": {
|
684 |
-
"version": "0.2.0",
|
685 |
-
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz",
|
686 |
-
"integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U=",
|
687 |
-
"dev": true,
|
688 |
-
"optional": true
|
689 |
-
},
|
690 |
-
"eachr": {
|
691 |
-
"version": "3.2.0",
|
692 |
-
"resolved": "https://registry.npmjs.org/eachr/-/eachr-3.2.0.tgz",
|
693 |
-
"integrity": "sha1-LDXkPqCGUW95l8+At6pk1VpKRIQ=",
|
694 |
-
"dev": true,
|
695 |
-
"requires": {
|
696 |
-
"editions": "1.3.3",
|
697 |
-
"typechecker": "4.4.1"
|
698 |
-
}
|
699 |
-
},
|
700 |
-
"ecc-jsbn": {
|
701 |
-
"version": "0.1.1",
|
702 |
-
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
703 |
-
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
704 |
-
"dev": true,
|
705 |
-
"optional": true,
|
706 |
-
"requires": {
|
707 |
-
"jsbn": "0.1.1"
|
708 |
-
}
|
709 |
-
},
|
710 |
-
"editions": {
|
711 |
-
"version": "1.3.3",
|
712 |
-
"resolved": "https://registry.npmjs.org/editions/-/editions-1.3.3.tgz",
|
713 |
-
"integrity": "sha1-CQcQG92iD6w8vjNMJ8vQaI3Jmls=",
|
714 |
-
"dev": true
|
715 |
-
},
|
716 |
-
"end-of-stream": {
|
717 |
-
"version": "1.4.0",
|
718 |
-
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
|
719 |
-
"integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
|
720 |
-
"dev": true,
|
721 |
-
"requires": {
|
722 |
-
"once": "1.4.0"
|
723 |
-
}
|
724 |
-
},
|
725 |
-
"error-ex": {
|
726 |
-
"version": "1.3.1",
|
727 |
-
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
|
728 |
-
"integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
|
729 |
-
"dev": true,
|
730 |
-
"requires": {
|
731 |
-
"is-arrayish": "0.2.1"
|
732 |
-
}
|
733 |
-
},
|
734 |
-
"escape-string-regexp": {
|
735 |
-
"version": "1.0.5",
|
736 |
-
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
737 |
-
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
738 |
-
"dev": true
|
739 |
-
},
|
740 |
-
"esprima": {
|
741 |
-
"version": "2.7.3",
|
742 |
-
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
|
743 |
-
"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
|
744 |
-
"dev": true
|
745 |
-
},
|
746 |
-
"eventemitter2": {
|
747 |
-
"version": "0.4.14",
|
748 |
-
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
|
749 |
-
"integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
|
750 |
-
"dev": true
|
751 |
-
},
|
752 |
-
"exit": {
|
753 |
-
"version": "0.1.2",
|
754 |
-
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
755 |
-
"integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
|
756 |
-
"dev": true
|
757 |
-
},
|
758 |
-
"expand-template": {
|
759 |
-
"version": "1.1.0",
|
760 |
-
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.0.tgz",
|
761 |
-
"integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==",
|
762 |
-
"dev": true,
|
763 |
-
"optional": true
|
764 |
-
},
|
765 |
-
"extend": {
|
766 |
-
"version": "3.0.1",
|
767 |
-
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
768 |
-
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
|
769 |
-
"dev": true,
|
770 |
-
"optional": true
|
771 |
-
},
|
772 |
-
"extract-opts": {
|
773 |
-
"version": "3.3.1",
|
774 |
-
"resolved": "https://registry.npmjs.org/extract-opts/-/extract-opts-3.3.1.tgz",
|
775 |
-
"integrity": "sha1-WrvtyYwNUgLjJ4cn+Rktfghsa+E=",
|
776 |
-
"dev": true,
|
777 |
-
"requires": {
|
778 |
-
"eachr": "3.2.0",
|
779 |
-
"editions": "1.3.3",
|
780 |
-
"typechecker": "4.4.1"
|
781 |
-
}
|
782 |
-
},
|
783 |
-
"extsprintf": {
|
784 |
-
"version": "1.3.0",
|
785 |
-
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
786 |
-
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
787 |
-
"dev": true
|
788 |
-
},
|
789 |
-
"fast-deep-equal": {
|
790 |
-
"version": "1.0.0",
|
791 |
-
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
|
792 |
-
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
|
793 |
-
"dev": true,
|
794 |
-
"optional": true
|
795 |
-
},
|
796 |
-
"fast-json-stable-stringify": {
|
797 |
-
"version": "2.0.0",
|
798 |
-
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
799 |
-
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
|
800 |
-
"dev": true,
|
801 |
-
"optional": true
|
802 |
-
},
|
803 |
-
"figures": {
|
804 |
-
"version": "1.7.0",
|
805 |
-
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
|
806 |
-
"integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
|
807 |
-
"dev": true,
|
808 |
-
"requires": {
|
809 |
-
"escape-string-regexp": "1.0.5",
|
810 |
-
"object-assign": "4.1.1"
|
811 |
-
}
|
812 |
-
},
|
813 |
-
"find-up": {
|
814 |
-
"version": "1.1.2",
|
815 |
-
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
|
816 |
-
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
|
817 |
-
"dev": true,
|
818 |
-
"requires": {
|
819 |
-
"path-exists": "2.1.0",
|
820 |
-
"pinkie-promise": "2.0.1"
|
821 |
-
}
|
822 |
-
},
|
823 |
-
"findup-sync": {
|
824 |
-
"version": "0.3.0",
|
825 |
-
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
|
826 |
-
"integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
|
827 |
-
"dev": true,
|
828 |
-
"requires": {
|
829 |
-
"glob": "5.0.15"
|
830 |
-
},
|
831 |
-
"dependencies": {
|
832 |
-
"glob": {
|
833 |
-
"version": "5.0.15",
|
834 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
|
835 |
-
"integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
|
836 |
-
"dev": true,
|
837 |
-
"requires": {
|
838 |
-
"inflight": "1.0.6",
|
839 |
-
"inherits": "2.0.3",
|
840 |
-
"minimatch": "3.0.4",
|
841 |
-
"once": "1.4.0",
|
842 |
-
"path-is-absolute": "1.0.1"
|
843 |
-
}
|
844 |
-
},
|
845 |
-
"minimatch": {
|
846 |
-
"version": "3.0.4",
|
847 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
848 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
849 |
-
"dev": true,
|
850 |
-
"requires": {
|
851 |
-
"brace-expansion": "1.1.8"
|
852 |
-
}
|
853 |
-
}
|
854 |
-
}
|
855 |
-
},
|
856 |
-
"forever-agent": {
|
857 |
-
"version": "0.6.1",
|
858 |
-
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
859 |
-
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
|
860 |
-
"dev": true,
|
861 |
-
"optional": true
|
862 |
-
},
|
863 |
-
"form-data": {
|
864 |
-
"version": "2.3.1",
|
865 |
-
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
|
866 |
-
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
|
867 |
-
"dev": true,
|
868 |
-
"optional": true,
|
869 |
-
"requires": {
|
870 |
-
"asynckit": "0.4.0",
|
871 |
-
"combined-stream": "1.0.5",
|
872 |
-
"mime-types": "2.1.17"
|
873 |
-
}
|
874 |
-
},
|
875 |
-
"fs.realpath": {
|
876 |
-
"version": "1.0.0",
|
877 |
-
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
878 |
-
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
879 |
-
"dev": true
|
880 |
-
},
|
881 |
-
"fstream": {
|
882 |
-
"version": "1.0.11",
|
883 |
-
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
|
884 |
-
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
|
885 |
-
"dev": true,
|
886 |
-
"requires": {
|
887 |
-
"graceful-fs": "4.1.11",
|
888 |
-
"inherits": "2.0.3",
|
889 |
-
"mkdirp": "0.5.1",
|
890 |
-
"rimraf": "2.2.8"
|
891 |
-
},
|
892 |
-
"dependencies": {
|
893 |
-
"graceful-fs": {
|
894 |
-
"version": "4.1.11",
|
895 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
896 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
897 |
-
"dev": true
|
898 |
-
}
|
899 |
-
}
|
900 |
-
},
|
901 |
-
"gauge": {
|
902 |
-
"version": "2.7.4",
|
903 |
-
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
904 |
-
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
905 |
-
"dev": true,
|
906 |
-
"requires": {
|
907 |
-
"aproba": "1.2.0",
|
908 |
-
"console-control-strings": "1.1.0",
|
909 |
-
"has-unicode": "2.0.1",
|
910 |
-
"object-assign": "4.1.1",
|
911 |
-
"signal-exit": "3.0.2",
|
912 |
-
"string-width": "1.0.2",
|
913 |
-
"strip-ansi": "3.0.1",
|
914 |
-
"wide-align": "1.1.2"
|
915 |
-
},
|
916 |
-
"dependencies": {
|
917 |
-
"ansi-regex": {
|
918 |
-
"version": "2.1.1",
|
919 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
920 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
921 |
-
"dev": true
|
922 |
-
},
|
923 |
-
"strip-ansi": {
|
924 |
-
"version": "3.0.1",
|
925 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
926 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
927 |
-
"dev": true,
|
928 |
-
"requires": {
|
929 |
-
"ansi-regex": "2.1.1"
|
930 |
-
}
|
931 |
-
}
|
932 |
-
}
|
933 |
-
},
|
934 |
-
"get-stdin": {
|
935 |
-
"version": "4.0.1",
|
936 |
-
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
937 |
-
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
|
938 |
-
"dev": true
|
939 |
-
},
|
940 |
-
"getobject": {
|
941 |
-
"version": "0.1.0",
|
942 |
-
"resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
|
943 |
-
"integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
|
944 |
-
"dev": true
|
945 |
-
},
|
946 |
-
"getpass": {
|
947 |
-
"version": "0.1.7",
|
948 |
-
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
949 |
-
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
950 |
-
"dev": true,
|
951 |
-
"optional": true,
|
952 |
-
"requires": {
|
953 |
-
"assert-plus": "1.0.0"
|
954 |
-
}
|
955 |
-
},
|
956 |
-
"github-from-package": {
|
957 |
-
"version": "0.0.0",
|
958 |
-
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
959 |
-
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
|
960 |
-
"dev": true,
|
961 |
-
"optional": true
|
962 |
-
},
|
963 |
-
"glob": {
|
964 |
-
"version": "3.1.21",
|
965 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
|
966 |
-
"integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
|
967 |
-
"dev": true,
|
968 |
-
"requires": {
|
969 |
-
"graceful-fs": "1.2.3",
|
970 |
-
"inherits": "1.0.2",
|
971 |
-
"minimatch": "0.2.14"
|
972 |
-
},
|
973 |
-
"dependencies": {
|
974 |
-
"inherits": {
|
975 |
-
"version": "1.0.2",
|
976 |
-
"resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz",
|
977 |
-
"integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=",
|
978 |
-
"dev": true
|
979 |
-
}
|
980 |
-
}
|
981 |
-
},
|
982 |
-
"graceful-fs": {
|
983 |
-
"version": "1.2.3",
|
984 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz",
|
985 |
-
"integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=",
|
986 |
-
"dev": true
|
987 |
-
},
|
988 |
-
"graceful-readlink": {
|
989 |
-
"version": "1.0.1",
|
990 |
-
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
991 |
-
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
|
992 |
-
"dev": true
|
993 |
-
},
|
994 |
-
"grunt": {
|
995 |
-
"version": "1.0.1",
|
996 |
-
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
|
997 |
-
"integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=",
|
998 |
-
"dev": true,
|
999 |
-
"requires": {
|
1000 |
-
"coffee-script": "1.10.0",
|
1001 |
-
"dateformat": "1.0.12",
|
1002 |
-
"eventemitter2": "0.4.14",
|
1003 |
-
"exit": "0.1.2",
|
1004 |
-
"findup-sync": "0.3.0",
|
1005 |
-
"glob": "7.0.6",
|
1006 |
-
"grunt-cli": "1.2.0",
|
1007 |
-
"grunt-known-options": "1.1.0",
|
1008 |
-
"grunt-legacy-log": "1.0.0",
|
1009 |
-
"grunt-legacy-util": "1.0.0",
|
1010 |
-
"iconv-lite": "0.4.19",
|
1011 |
-
"js-yaml": "3.5.5",
|
1012 |
-
"minimatch": "3.0.4",
|
1013 |
-
"nopt": "3.0.6",
|
1014 |
-
"path-is-absolute": "1.0.1",
|
1015 |
-
"rimraf": "2.2.8"
|
1016 |
-
},
|
1017 |
-
"dependencies": {
|
1018 |
-
"glob": {
|
1019 |
-
"version": "7.0.6",
|
1020 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
|
1021 |
-
"integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
|
1022 |
-
"dev": true,
|
1023 |
-
"requires": {
|
1024 |
-
"fs.realpath": "1.0.0",
|
1025 |
-
"inflight": "1.0.6",
|
1026 |
-
"inherits": "2.0.3",
|
1027 |
-
"minimatch": "3.0.4",
|
1028 |
-
"once": "1.4.0",
|
1029 |
-
"path-is-absolute": "1.0.1"
|
1030 |
-
}
|
1031 |
-
},
|
1032 |
-
"grunt-cli": {
|
1033 |
-
"version": "1.2.0",
|
1034 |
-
"resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
|
1035 |
-
"integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
|
1036 |
-
"dev": true,
|
1037 |
-
"requires": {
|
1038 |
-
"findup-sync": "0.3.0",
|
1039 |
-
"grunt-known-options": "1.1.0",
|
1040 |
-
"nopt": "3.0.6",
|
1041 |
-
"resolve": "1.1.7"
|
1042 |
-
}
|
1043 |
-
},
|
1044 |
-
"minimatch": {
|
1045 |
-
"version": "3.0.4",
|
1046 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
1047 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
1048 |
-
"dev": true,
|
1049 |
-
"requires": {
|
1050 |
-
"brace-expansion": "1.1.8"
|
1051 |
-
}
|
1052 |
-
}
|
1053 |
-
}
|
1054 |
-
},
|
1055 |
-
"grunt-contrib-clean": {
|
1056 |
-
"version": "0.6.0",
|
1057 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.6.0.tgz",
|
1058 |
-
"integrity": "sha1-9TLbpLghJnTHwBPhRr2mY4uQSPY=",
|
1059 |
-
"dev": true,
|
1060 |
-
"requires": {
|
1061 |
-
"rimraf": "2.2.8"
|
1062 |
-
}
|
1063 |
-
},
|
1064 |
-
"grunt-contrib-compress": {
|
1065 |
-
"version": "1.4.3",
|
1066 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-1.4.3.tgz",
|
1067 |
-
"integrity": "sha1-Ac7/ucY39S5wgfRjdQmD0KOw+nM=",
|
1068 |
-
"dev": true,
|
1069 |
-
"requires": {
|
1070 |
-
"archiver": "1.3.0",
|
1071 |
-
"chalk": "1.1.3",
|
1072 |
-
"iltorb": "1.3.10",
|
1073 |
-
"lodash": "4.17.4",
|
1074 |
-
"pretty-bytes": "4.0.2",
|
1075 |
-
"stream-buffers": "2.2.0"
|
1076 |
-
},
|
1077 |
-
"dependencies": {
|
1078 |
-
"ansi-regex": {
|
1079 |
-
"version": "2.1.1",
|
1080 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
1081 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
1082 |
-
"dev": true
|
1083 |
-
},
|
1084 |
-
"ansi-styles": {
|
1085 |
-
"version": "2.2.1",
|
1086 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
1087 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
1088 |
-
"dev": true
|
1089 |
-
},
|
1090 |
-
"chalk": {
|
1091 |
-
"version": "1.1.3",
|
1092 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
1093 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
1094 |
-
"dev": true,
|
1095 |
-
"requires": {
|
1096 |
-
"ansi-styles": "2.2.1",
|
1097 |
-
"escape-string-regexp": "1.0.5",
|
1098 |
-
"has-ansi": "2.0.0",
|
1099 |
-
"strip-ansi": "3.0.1",
|
1100 |
-
"supports-color": "2.0.0"
|
1101 |
-
}
|
1102 |
-
},
|
1103 |
-
"has-ansi": {
|
1104 |
-
"version": "2.0.0",
|
1105 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
1106 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
1107 |
-
"dev": true,
|
1108 |
-
"requires": {
|
1109 |
-
"ansi-regex": "2.1.1"
|
1110 |
-
}
|
1111 |
-
},
|
1112 |
-
"lodash": {
|
1113 |
-
"version": "4.17.4",
|
1114 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
1115 |
-
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
1116 |
-
"dev": true
|
1117 |
-
},
|
1118 |
-
"pretty-bytes": {
|
1119 |
-
"version": "4.0.2",
|
1120 |
-
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz",
|
1121 |
-
"integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=",
|
1122 |
-
"dev": true
|
1123 |
-
},
|
1124 |
-
"strip-ansi": {
|
1125 |
-
"version": "3.0.1",
|
1126 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
1127 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
1128 |
-
"dev": true,
|
1129 |
-
"requires": {
|
1130 |
-
"ansi-regex": "2.1.1"
|
1131 |
-
}
|
1132 |
-
},
|
1133 |
-
"supports-color": {
|
1134 |
-
"version": "2.0.0",
|
1135 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
1136 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
1137 |
-
"dev": true
|
1138 |
-
}
|
1139 |
-
}
|
1140 |
-
},
|
1141 |
-
"grunt-contrib-copy": {
|
1142 |
-
"version": "0.7.0",
|
1143 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.7.0.tgz",
|
1144 |
-
"integrity": "sha1-xt5I4N9zFEmu2w8InAldvCpVBQ8=",
|
1145 |
-
"dev": true,
|
1146 |
-
"requires": {
|
1147 |
-
"chalk": "0.5.1"
|
1148 |
-
}
|
1149 |
-
},
|
1150 |
-
"grunt-contrib-cssmin": {
|
1151 |
-
"version": "0.12.3",
|
1152 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-0.12.3.tgz",
|
1153 |
-
"integrity": "sha1-QVdZYJb7dlb8RktMx7B0beHzkBQ=",
|
1154 |
-
"dev": true,
|
1155 |
-
"requires": {
|
1156 |
-
"chalk": "1.1.3",
|
1157 |
-
"clean-css": "3.4.28",
|
1158 |
-
"maxmin": "1.1.0"
|
1159 |
-
},
|
1160 |
-
"dependencies": {
|
1161 |
-
"ansi-regex": {
|
1162 |
-
"version": "2.1.1",
|
1163 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
1164 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
1165 |
-
"dev": true
|
1166 |
-
},
|
1167 |
-
"ansi-styles": {
|
1168 |
-
"version": "2.2.1",
|
1169 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
1170 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
1171 |
-
"dev": true
|
1172 |
-
},
|
1173 |
-
"chalk": {
|
1174 |
-
"version": "1.1.3",
|
1175 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
1176 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
1177 |
-
"dev": true,
|
1178 |
-
"requires": {
|
1179 |
-
"ansi-styles": "2.2.1",
|
1180 |
-
"escape-string-regexp": "1.0.5",
|
1181 |
-
"has-ansi": "2.0.0",
|
1182 |
-
"strip-ansi": "3.0.1",
|
1183 |
-
"supports-color": "2.0.0"
|
1184 |
-
}
|
1185 |
-
},
|
1186 |
-
"has-ansi": {
|
1187 |
-
"version": "2.0.0",
|
1188 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
1189 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
1190 |
-
"dev": true,
|
1191 |
-
"requires": {
|
1192 |
-
"ansi-regex": "2.1.1"
|
1193 |
-
}
|
1194 |
-
},
|
1195 |
-
"strip-ansi": {
|
1196 |
-
"version": "3.0.1",
|
1197 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
1198 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
1199 |
-
"dev": true,
|
1200 |
-
"requires": {
|
1201 |
-
"ansi-regex": "2.1.1"
|
1202 |
-
}
|
1203 |
-
},
|
1204 |
-
"supports-color": {
|
1205 |
-
"version": "2.0.0",
|
1206 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
1207 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
1208 |
-
"dev": true
|
1209 |
-
}
|
1210 |
-
}
|
1211 |
-
},
|
1212 |
-
"grunt-contrib-jshint": {
|
1213 |
-
"version": "0.6.5",
|
1214 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.6.5.tgz",
|
1215 |
-
"integrity": "sha1-OvtGdnRTZMxKGe7nk0wOBgCLVm4=",
|
1216 |
-
"dev": true,
|
1217 |
-
"requires": {
|
1218 |
-
"jshint": "2.1.11"
|
1219 |
-
}
|
1220 |
-
},
|
1221 |
-
"grunt-contrib-uglify": {
|
1222 |
-
"version": "0.2.7",
|
1223 |
-
"resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.2.7.tgz",
|
1224 |
-
"integrity": "sha1-5r2lHgxAoUWfbOrUI8Ze/XJaG/c=",
|
1225 |
-
"dev": true,
|
1226 |
-
"requires": {
|
1227 |
-
"grunt-lib-contrib": "0.6.1",
|
1228 |
-
"uglify-js": "2.4.24"
|
1229 |
-
}
|
1230 |
-
},
|
1231 |
-
"grunt-known-options": {
|
1232 |
-
"version": "1.1.0",
|
1233 |
-
"resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
|
1234 |
-
"integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=",
|
1235 |
-
"dev": true
|
1236 |
-
},
|
1237 |
-
"grunt-legacy-log": {
|
1238 |
-
"version": "1.0.0",
|
1239 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz",
|
1240 |
-
"integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=",
|
1241 |
-
"dev": true,
|
1242 |
-
"requires": {
|
1243 |
-
"colors": "1.1.2",
|
1244 |
-
"grunt-legacy-log-utils": "1.0.0",
|
1245 |
-
"hooker": "0.2.3",
|
1246 |
-
"lodash": "3.10.1",
|
1247 |
-
"underscore.string": "3.2.3"
|
1248 |
-
}
|
1249 |
-
},
|
1250 |
-
"grunt-legacy-log-utils": {
|
1251 |
-
"version": "1.0.0",
|
1252 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz",
|
1253 |
-
"integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=",
|
1254 |
-
"dev": true,
|
1255 |
-
"requires": {
|
1256 |
-
"chalk": "1.1.3",
|
1257 |
-
"lodash": "4.3.0"
|
1258 |
-
},
|
1259 |
-
"dependencies": {
|
1260 |
-
"ansi-regex": {
|
1261 |
-
"version": "2.1.1",
|
1262 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
1263 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
1264 |
-
"dev": true
|
1265 |
-
},
|
1266 |
-
"ansi-styles": {
|
1267 |
-
"version": "2.2.1",
|
1268 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
1269 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
1270 |
-
"dev": true
|
1271 |
-
},
|
1272 |
-
"chalk": {
|
1273 |
-
"version": "1.1.3",
|
1274 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
1275 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
1276 |
-
"dev": true,
|
1277 |
-
"requires": {
|
1278 |
-
"ansi-styles": "2.2.1",
|
1279 |
-
"escape-string-regexp": "1.0.5",
|
1280 |
-
"has-ansi": "2.0.0",
|
1281 |
-
"strip-ansi": "3.0.1",
|
1282 |
-
"supports-color": "2.0.0"
|
1283 |
-
}
|
1284 |
-
},
|
1285 |
-
"has-ansi": {
|
1286 |
-
"version": "2.0.0",
|
1287 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
1288 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
1289 |
-
"dev": true,
|
1290 |
-
"requires": {
|
1291 |
-
"ansi-regex": "2.1.1"
|
1292 |
-
}
|
1293 |
-
},
|
1294 |
-
"lodash": {
|
1295 |
-
"version": "4.3.0",
|
1296 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
|
1297 |
-
"integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
|
1298 |
-
"dev": true
|
1299 |
-
},
|
1300 |
-
"strip-ansi": {
|
1301 |
-
"version": "3.0.1",
|
1302 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
1303 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
1304 |
-
"dev": true,
|
1305 |
-
"requires": {
|
1306 |
-
"ansi-regex": "2.1.1"
|
1307 |
-
}
|
1308 |
-
},
|
1309 |
-
"supports-color": {
|
1310 |
-
"version": "2.0.0",
|
1311 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
1312 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
1313 |
-
"dev": true
|
1314 |
-
}
|
1315 |
-
}
|
1316 |
-
},
|
1317 |
-
"grunt-legacy-util": {
|
1318 |
-
"version": "1.0.0",
|
1319 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz",
|
1320 |
-
"integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=",
|
1321 |
-
"dev": true,
|
1322 |
-
"requires": {
|
1323 |
-
"async": "1.5.2",
|
1324 |
-
"exit": "0.1.2",
|
1325 |
-
"getobject": "0.1.0",
|
1326 |
-
"hooker": "0.2.3",
|
1327 |
-
"lodash": "4.3.0",
|
1328 |
-
"underscore.string": "3.2.3",
|
1329 |
-
"which": "1.2.14"
|
1330 |
-
},
|
1331 |
-
"dependencies": {
|
1332 |
-
"lodash": {
|
1333 |
-
"version": "4.3.0",
|
1334 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
|
1335 |
-
"integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
|
1336 |
-
"dev": true
|
1337 |
-
}
|
1338 |
-
}
|
1339 |
-
},
|
1340 |
-
"grunt-lib-contrib": {
|
1341 |
-
"version": "0.6.1",
|
1342 |
-
"resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz",
|
1343 |
-
"integrity": "sha1-P1att9oG6BR5XuJBWw6+X7iQPrs=",
|
1344 |
-
"dev": true,
|
1345 |
-
"requires": {
|
1346 |
-
"zlib-browserify": "0.0.1"
|
1347 |
-
}
|
1348 |
-
},
|
1349 |
-
"grunt-phplint": {
|
1350 |
-
"version": "0.0.8",
|
1351 |
-
"resolved": "https://registry.npmjs.org/grunt-phplint/-/grunt-phplint-0.0.8.tgz",
|
1352 |
-
"integrity": "sha1-wSeqKP930jnBSgHwUMx7cVnOkMA=",
|
1353 |
-
"dev": true,
|
1354 |
-
"requires": {
|
1355 |
-
"cache-swap": "0.0.6",
|
1356 |
-
"grunt": "0.4.5"
|
1357 |
-
},
|
1358 |
-
"dependencies": {
|
1359 |
-
"argparse": {
|
1360 |
-
"version": "0.1.16",
|
1361 |
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz",
|
1362 |
-
"integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=",
|
1363 |
-
"dev": true,
|
1364 |
-
"requires": {
|
1365 |
-
"underscore": "1.7.0",
|
1366 |
-
"underscore.string": "2.4.0"
|
1367 |
-
},
|
1368 |
-
"dependencies": {
|
1369 |
-
"underscore.string": {
|
1370 |
-
"version": "2.4.0",
|
1371 |
-
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
|
1372 |
-
"integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=",
|
1373 |
-
"dev": true
|
1374 |
-
}
|
1375 |
-
}
|
1376 |
-
},
|
1377 |
-
"async": {
|
1378 |
-
"version": "0.1.22",
|
1379 |
-
"resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz",
|
1380 |
-
"integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=",
|
1381 |
-
"dev": true
|
1382 |
-
},
|
1383 |
-
"coffee-script": {
|
1384 |
-
"version": "1.3.3",
|
1385 |
-
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz",
|
1386 |
-
"integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=",
|
1387 |
-
"dev": true
|
1388 |
-
},
|
1389 |
-
"colors": {
|
1390 |
-
"version": "0.6.2",
|
1391 |
-
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
1392 |
-
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=",
|
1393 |
-
"dev": true
|
1394 |
-
},
|
1395 |
-
"dateformat": {
|
1396 |
-
"version": "1.0.2-1.2.3",
|
1397 |
-
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz",
|
1398 |
-
"integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=",
|
1399 |
-
"dev": true
|
1400 |
-
},
|
1401 |
-
"esprima": {
|
1402 |
-
"version": "1.0.4",
|
1403 |
-
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
|
1404 |
-
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=",
|
1405 |
-
"dev": true
|
1406 |
-
},
|
1407 |
-
"findup-sync": {
|
1408 |
-
"version": "0.1.3",
|
1409 |
-
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz",
|
1410 |
-
"integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=",
|
1411 |
-
"dev": true,
|
1412 |
-
"requires": {
|
1413 |
-
"glob": "3.2.11",
|
1414 |
-
"lodash": "2.4.2"
|
1415 |
-
},
|
1416 |
-
"dependencies": {
|
1417 |
-
"glob": {
|
1418 |
-
"version": "3.2.11",
|
1419 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
|
1420 |
-
"integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
|
1421 |
-
"dev": true,
|
1422 |
-
"requires": {
|
1423 |
-
"inherits": "2.0.3",
|
1424 |
-
"minimatch": "0.3.0"
|
1425 |
-
}
|
1426 |
-
},
|
1427 |
-
"lodash": {
|
1428 |
-
"version": "2.4.2",
|
1429 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
|
1430 |
-
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
|
1431 |
-
"dev": true
|
1432 |
-
},
|
1433 |
-
"minimatch": {
|
1434 |
-
"version": "0.3.0",
|
1435 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
|
1436 |
-
"integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
|
1437 |
-
"dev": true,
|
1438 |
-
"requires": {
|
1439 |
-
"lru-cache": "2.7.3",
|
1440 |
-
"sigmund": "1.0.1"
|
1441 |
-
}
|
1442 |
-
}
|
1443 |
-
}
|
1444 |
-
},
|
1445 |
-
"grunt": {
|
1446 |
-
"version": "0.4.5",
|
1447 |
-
"resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz",
|
1448 |
-
"integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=",
|
1449 |
-
"dev": true,
|
1450 |
-
"requires": {
|
1451 |
-
"async": "0.1.22",
|
1452 |
-
"coffee-script": "1.3.3",
|
1453 |
-
"colors": "0.6.2",
|
1454 |
-
"dateformat": "1.0.2-1.2.3",
|
1455 |
-
"eventemitter2": "0.4.14",
|
1456 |
-
"exit": "0.1.2",
|
1457 |
-
"findup-sync": "0.1.3",
|
1458 |
-
"getobject": "0.1.0",
|
1459 |
-
"glob": "3.1.21",
|
1460 |
-
"grunt-legacy-log": "0.1.3",
|
1461 |
-
"grunt-legacy-util": "0.2.0",
|
1462 |
-
"hooker": "0.2.3",
|
1463 |
-
"iconv-lite": "0.2.11",
|
1464 |
-
"js-yaml": "2.0.5",
|
1465 |
-
"lodash": "0.9.2",
|
1466 |
-
"minimatch": "0.2.14",
|
1467 |
-
"nopt": "1.0.10",
|
1468 |
-
"rimraf": "2.2.8",
|
1469 |
-
"underscore.string": "2.2.1",
|
1470 |
-
"which": "1.0.9"
|
1471 |
-
}
|
1472 |
-
},
|
1473 |
-
"grunt-legacy-log": {
|
1474 |
-
"version": "0.1.3",
|
1475 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz",
|
1476 |
-
"integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=",
|
1477 |
-
"dev": true,
|
1478 |
-
"requires": {
|
1479 |
-
"colors": "0.6.2",
|
1480 |
-
"grunt-legacy-log-utils": "0.1.1",
|
1481 |
-
"hooker": "0.2.3",
|
1482 |
-
"lodash": "2.4.2",
|
1483 |
-
"underscore.string": "2.3.3"
|
1484 |
-
},
|
1485 |
-
"dependencies": {
|
1486 |
-
"lodash": {
|
1487 |
-
"version": "2.4.2",
|
1488 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
|
1489 |
-
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
|
1490 |
-
"dev": true
|
1491 |
-
},
|
1492 |
-
"underscore.string": {
|
1493 |
-
"version": "2.3.3",
|
1494 |
-
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
|
1495 |
-
"integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
|
1496 |
-
"dev": true
|
1497 |
-
}
|
1498 |
-
}
|
1499 |
-
},
|
1500 |
-
"grunt-legacy-log-utils": {
|
1501 |
-
"version": "0.1.1",
|
1502 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz",
|
1503 |
-
"integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=",
|
1504 |
-
"dev": true,
|
1505 |
-
"requires": {
|
1506 |
-
"colors": "0.6.2",
|
1507 |
-
"lodash": "2.4.2",
|
1508 |
-
"underscore.string": "2.3.3"
|
1509 |
-
},
|
1510 |
-
"dependencies": {
|
1511 |
-
"lodash": {
|
1512 |
-
"version": "2.4.2",
|
1513 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
|
1514 |
-
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
|
1515 |
-
"dev": true
|
1516 |
-
},
|
1517 |
-
"underscore.string": {
|
1518 |
-
"version": "2.3.3",
|
1519 |
-
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
|
1520 |
-
"integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
|
1521 |
-
"dev": true
|
1522 |
-
}
|
1523 |
-
}
|
1524 |
-
},
|
1525 |
-
"grunt-legacy-util": {
|
1526 |
-
"version": "0.2.0",
|
1527 |
-
"resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz",
|
1528 |
-
"integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=",
|
1529 |
-
"dev": true,
|
1530 |
-
"requires": {
|
1531 |
-
"async": "0.1.22",
|
1532 |
-
"exit": "0.1.2",
|
1533 |
-
"getobject": "0.1.0",
|
1534 |
-
"hooker": "0.2.3",
|
1535 |
-
"lodash": "0.9.2",
|
1536 |
-
"underscore.string": "2.2.1",
|
1537 |
-
"which": "1.0.9"
|
1538 |
-
}
|
1539 |
-
},
|
1540 |
-
"iconv-lite": {
|
1541 |
-
"version": "0.2.11",
|
1542 |
-
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz",
|
1543 |
-
"integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=",
|
1544 |
-
"dev": true
|
1545 |
-
},
|
1546 |
-
"js-yaml": {
|
1547 |
-
"version": "2.0.5",
|
1548 |
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz",
|
1549 |
-
"integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=",
|
1550 |
-
"dev": true,
|
1551 |
-
"requires": {
|
1552 |
-
"argparse": "0.1.16",
|
1553 |
-
"esprima": "1.0.4"
|
1554 |
-
}
|
1555 |
-
},
|
1556 |
-
"lodash": {
|
1557 |
-
"version": "0.9.2",
|
1558 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz",
|
1559 |
-
"integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=",
|
1560 |
-
"dev": true
|
1561 |
-
},
|
1562 |
-
"nopt": {
|
1563 |
-
"version": "1.0.10",
|
1564 |
-
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
|
1565 |
-
"integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
|
1566 |
-
"dev": true,
|
1567 |
-
"requires": {
|
1568 |
-
"abbrev": "1.1.1"
|
1569 |
-
}
|
1570 |
-
},
|
1571 |
-
"underscore.string": {
|
1572 |
-
"version": "2.2.1",
|
1573 |
-
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz",
|
1574 |
-
"integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=",
|
1575 |
-
"dev": true
|
1576 |
-
},
|
1577 |
-
"which": {
|
1578 |
-
"version": "1.0.9",
|
1579 |
-
"resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz",
|
1580 |
-
"integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=",
|
1581 |
-
"dev": true
|
1582 |
-
}
|
1583 |
-
}
|
1584 |
-
},
|
1585 |
-
"grunt-string-replace": {
|
1586 |
-
"version": "1.2.1",
|
1587 |
-
"resolved": "https://registry.npmjs.org/grunt-string-replace/-/grunt-string-replace-1.2.1.tgz",
|
1588 |
-
"integrity": "sha1-c9tiSuiyVNfB52LVGgPgQOEHIcY=",
|
1589 |
-
"dev": true,
|
1590 |
-
"requires": {
|
1591 |
-
"async": "1.5.2",
|
1592 |
-
"chalk": "1.1.3"
|
1593 |
-
},
|
1594 |
-
"dependencies": {
|
1595 |
-
"ansi-regex": {
|
1596 |
-
"version": "2.1.1",
|
1597 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
1598 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
1599 |
-
"dev": true
|
1600 |
-
},
|
1601 |
-
"ansi-styles": {
|
1602 |
-
"version": "2.2.1",
|
1603 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
1604 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
1605 |
-
"dev": true
|
1606 |
-
},
|
1607 |
-
"async": {
|
1608 |
-
"version": "1.5.2",
|
1609 |
-
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
1610 |
-
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
1611 |
-
"dev": true
|
1612 |
-
},
|
1613 |
-
"chalk": {
|
1614 |
-
"version": "1.1.3",
|
1615 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
1616 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
1617 |
-
"dev": true,
|
1618 |
-
"requires": {
|
1619 |
-
"ansi-styles": "2.2.1",
|
1620 |
-
"escape-string-regexp": "1.0.5",
|
1621 |
-
"has-ansi": "2.0.0",
|
1622 |
-
"strip-ansi": "3.0.1",
|
1623 |
-
"supports-color": "2.0.0"
|
1624 |
-
}
|
1625 |
-
},
|
1626 |
-
"has-ansi": {
|
1627 |
-
"version": "2.0.0",
|
1628 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
1629 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
1630 |
-
"dev": true,
|
1631 |
-
"requires": {
|
1632 |
-
"ansi-regex": "2.1.1"
|
1633 |
-
}
|
1634 |
-
},
|
1635 |
-
"strip-ansi": {
|
1636 |
-
"version": "3.0.1",
|
1637 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
1638 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
1639 |
-
"dev": true,
|
1640 |
-
"requires": {
|
1641 |
-
"ansi-regex": "2.1.1"
|
1642 |
-
}
|
1643 |
-
},
|
1644 |
-
"supports-color": {
|
1645 |
-
"version": "2.0.0",
|
1646 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
1647 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
1648 |
-
"dev": true
|
1649 |
-
}
|
1650 |
-
}
|
1651 |
-
},
|
1652 |
-
"grunt-version": {
|
1653 |
-
"version": "1.2.1",
|
1654 |
-
"resolved": "https://registry.npmjs.org/grunt-version/-/grunt-version-1.2.1.tgz",
|
1655 |
-
"integrity": "sha512-FMRde7kCY1T2zCBAg4ZbLR9GbKDX60xCIZS89kCyk29LLQ/nbRSgXY+782HjT+HfC21kszcpWttfCGq1eERHPA==",
|
1656 |
-
"dev": true,
|
1657 |
-
"requires": {
|
1658 |
-
"grunt": "1.0.1",
|
1659 |
-
"semver": "4.3.6"
|
1660 |
-
},
|
1661 |
-
"dependencies": {
|
1662 |
-
"semver": {
|
1663 |
-
"version": "4.3.6",
|
1664 |
-
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
|
1665 |
-
"integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
|
1666 |
-
"dev": true
|
1667 |
-
}
|
1668 |
-
}
|
1669 |
-
},
|
1670 |
-
"gzip-size": {
|
1671 |
-
"version": "1.0.0",
|
1672 |
-
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz",
|
1673 |
-
"integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=",
|
1674 |
-
"dev": true,
|
1675 |
-
"requires": {
|
1676 |
-
"browserify-zlib": "0.1.4",
|
1677 |
-
"concat-stream": "1.6.0"
|
1678 |
-
}
|
1679 |
-
},
|
1680 |
-
"har-schema": {
|
1681 |
-
"version": "2.0.0",
|
1682 |
-
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
1683 |
-
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
1684 |
-
"dev": true,
|
1685 |
-
"optional": true
|
1686 |
-
},
|
1687 |
-
"har-validator": {
|
1688 |
-
"version": "5.0.3",
|
1689 |
-
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
1690 |
-
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
1691 |
-
"dev": true,
|
1692 |
-
"optional": true,
|
1693 |
-
"requires": {
|
1694 |
-
"ajv": "5.5.1",
|
1695 |
-
"har-schema": "2.0.0"
|
1696 |
-
}
|
1697 |
-
},
|
1698 |
-
"has-ansi": {
|
1699 |
-
"version": "0.1.0",
|
1700 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
|
1701 |
-
"integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
|
1702 |
-
"dev": true,
|
1703 |
-
"requires": {
|
1704 |
-
"ansi-regex": "0.2.1"
|
1705 |
-
}
|
1706 |
-
},
|
1707 |
-
"has-unicode": {
|
1708 |
-
"version": "2.0.1",
|
1709 |
-
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
1710 |
-
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
|
1711 |
-
"dev": true
|
1712 |
-
},
|
1713 |
-
"hawk": {
|
1714 |
-
"version": "6.0.2",
|
1715 |
-
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
|
1716 |
-
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
|
1717 |
-
"dev": true,
|
1718 |
-
"optional": true,
|
1719 |
-
"requires": {
|
1720 |
-
"boom": "4.3.1",
|
1721 |
-
"cryptiles": "3.1.2",
|
1722 |
-
"hoek": "4.2.0",
|
1723 |
-
"sntp": "2.1.0"
|
1724 |
-
}
|
1725 |
-
},
|
1726 |
-
"hoek": {
|
1727 |
-
"version": "4.2.0",
|
1728 |
-
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
|
1729 |
-
"integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==",
|
1730 |
-
"dev": true
|
1731 |
-
},
|
1732 |
-
"hooker": {
|
1733 |
-
"version": "0.2.3",
|
1734 |
-
"resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
|
1735 |
-
"integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
|
1736 |
-
"dev": true
|
1737 |
-
},
|
1738 |
-
"hosted-git-info": {
|
1739 |
-
"version": "2.5.0",
|
1740 |
-
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
|
1741 |
-
"integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
|
1742 |
-
"dev": true
|
1743 |
-
},
|
1744 |
-
"http-signature": {
|
1745 |
-
"version": "1.2.0",
|
1746 |
-
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
1747 |
-
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
1748 |
-
"dev": true,
|
1749 |
-
"optional": true,
|
1750 |
-
"requires": {
|
1751 |
-
"assert-plus": "1.0.0",
|
1752 |
-
"jsprim": "1.4.1",
|
1753 |
-
"sshpk": "1.13.1"
|
1754 |
-
}
|
1755 |
-
},
|
1756 |
-
"iconv-lite": {
|
1757 |
-
"version": "0.4.19",
|
1758 |
-
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
1759 |
-
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
|
1760 |
-
"dev": true
|
1761 |
-
},
|
1762 |
-
"iltorb": {
|
1763 |
-
"version": "1.3.10",
|
1764 |
-
"resolved": "https://registry.npmjs.org/iltorb/-/iltorb-1.3.10.tgz",
|
1765 |
-
"integrity": "sha512-nyB4+ru1u8CQqQ6w7YjasboKN3NQTN8GH/V/eEssNRKhW6UbdxdWhB9fJ5EEdjJfezKY0qPrcwLyIcgjL8hHxA==",
|
1766 |
-
"dev": true,
|
1767 |
-
"optional": true,
|
1768 |
-
"requires": {
|
1769 |
-
"detect-libc": "0.2.0",
|
1770 |
-
"nan": "2.8.0",
|
1771 |
-
"node-gyp": "3.6.2",
|
1772 |
-
"prebuild-install": "2.4.1"
|
1773 |
-
}
|
1774 |
-
},
|
1775 |
-
"indent-string": {
|
1776 |
-
"version": "2.1.0",
|
1777 |
-
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
|
1778 |
-
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
|
1779 |
-
"dev": true,
|
1780 |
-
"requires": {
|
1781 |
-
"repeating": "2.0.1"
|
1782 |
-
}
|
1783 |
-
},
|
1784 |
-
"inflight": {
|
1785 |
-
"version": "1.0.6",
|
1786 |
-
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
1787 |
-
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
1788 |
-
"dev": true,
|
1789 |
-
"requires": {
|
1790 |
-
"once": "1.4.0",
|
1791 |
-
"wrappy": "1.0.2"
|
1792 |
-
}
|
1793 |
-
},
|
1794 |
-
"inherit": {
|
1795 |
-
"version": "2.2.6",
|
1796 |
-
"resolved": "https://registry.npmjs.org/inherit/-/inherit-2.2.6.tgz",
|
1797 |
-
"integrity": "sha1-8WFLBshUToEo5CKchjR9tzrZeI0=",
|
1798 |
-
"dev": true
|
1799 |
-
},
|
1800 |
-
"inherits": {
|
1801 |
-
"version": "2.0.3",
|
1802 |
-
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
1803 |
-
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
1804 |
-
"dev": true
|
1805 |
-
},
|
1806 |
-
"ini": {
|
1807 |
-
"version": "1.3.5",
|
1808 |
-
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
1809 |
-
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
1810 |
-
"dev": true,
|
1811 |
-
"optional": true
|
1812 |
-
},
|
1813 |
-
"is-arrayish": {
|
1814 |
-
"version": "0.2.1",
|
1815 |
-
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
1816 |
-
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
1817 |
-
"dev": true
|
1818 |
-
},
|
1819 |
-
"is-builtin-module": {
|
1820 |
-
"version": "1.0.0",
|
1821 |
-
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
|
1822 |
-
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
|
1823 |
-
"dev": true,
|
1824 |
-
"requires": {
|
1825 |
-
"builtin-modules": "1.1.1"
|
1826 |
-
}
|
1827 |
-
},
|
1828 |
-
"is-finite": {
|
1829 |
-
"version": "1.0.2",
|
1830 |
-
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
|
1831 |
-
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
|
1832 |
-
"dev": true,
|
1833 |
-
"requires": {
|
1834 |
-
"number-is-nan": "1.0.1"
|
1835 |
-
}
|
1836 |
-
},
|
1837 |
-
"is-fullwidth-code-point": {
|
1838 |
-
"version": "1.0.0",
|
1839 |
-
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
1840 |
-
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
1841 |
-
"dev": true,
|
1842 |
-
"requires": {
|
1843 |
-
"number-is-nan": "1.0.1"
|
1844 |
-
}
|
1845 |
-
},
|
1846 |
-
"is-typedarray": {
|
1847 |
-
"version": "1.0.0",
|
1848 |
-
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
1849 |
-
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
1850 |
-
"dev": true,
|
1851 |
-
"optional": true
|
1852 |
-
},
|
1853 |
-
"is-utf8": {
|
1854 |
-
"version": "0.2.1",
|
1855 |
-
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
|
1856 |
-
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
|
1857 |
-
"dev": true
|
1858 |
-
},
|
1859 |
-
"isarray": {
|
1860 |
-
"version": "1.0.0",
|
1861 |
-
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
1862 |
-
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
1863 |
-
"dev": true
|
1864 |
-
},
|
1865 |
-
"isexe": {
|
1866 |
-
"version": "2.0.0",
|
1867 |
-
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
1868 |
-
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
1869 |
-
"dev": true
|
1870 |
-
},
|
1871 |
-
"isstream": {
|
1872 |
-
"version": "0.1.2",
|
1873 |
-
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
1874 |
-
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
1875 |
-
"dev": true,
|
1876 |
-
"optional": true
|
1877 |
-
},
|
1878 |
-
"jit-grunt": {
|
1879 |
-
"version": "0.10.0",
|
1880 |
-
"resolved": "https://registry.npmjs.org/jit-grunt/-/jit-grunt-0.10.0.tgz",
|
1881 |
-
"integrity": "sha1-AIw6f+Hpa9DYTiYOofoXg0V/ecI=",
|
1882 |
-
"dev": true
|
1883 |
-
},
|
1884 |
-
"js-yaml": {
|
1885 |
-
"version": "3.5.5",
|
1886 |
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
|
1887 |
-
"integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=",
|
1888 |
-
"dev": true,
|
1889 |
-
"requires": {
|
1890 |
-
"argparse": "1.0.9",
|
1891 |
-
"esprima": "2.7.3"
|
1892 |
-
}
|
1893 |
-
},
|
1894 |
-
"jsbn": {
|
1895 |
-
"version": "0.1.1",
|
1896 |
-
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
1897 |
-
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
1898 |
-
"dev": true,
|
1899 |
-
"optional": true
|
1900 |
-
},
|
1901 |
-
"jshint": {
|
1902 |
-
"version": "2.1.11",
|
1903 |
-
"resolved": "https://registry.npmjs.org/jshint/-/jshint-2.1.11.tgz",
|
1904 |
-
"integrity": "sha1-61EI/vm6Xd67gwmD9XLSQuSeP5Y=",
|
1905 |
-
"dev": true,
|
1906 |
-
"requires": {
|
1907 |
-
"cli": "0.4.5",
|
1908 |
-
"console-browserify": "0.1.6",
|
1909 |
-
"minimatch": "0.2.14",
|
1910 |
-
"shelljs": "0.1.4",
|
1911 |
-
"underscore": "1.4.4"
|
1912 |
-
},
|
1913 |
-
"dependencies": {
|
1914 |
-
"underscore": {
|
1915 |
-
"version": "1.4.4",
|
1916 |
-
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
|
1917 |
-
"integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=",
|
1918 |
-
"dev": true
|
1919 |
-
}
|
1920 |
-
}
|
1921 |
-
},
|
1922 |
-
"json-schema": {
|
1923 |
-
"version": "0.2.3",
|
1924 |
-
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
1925 |
-
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
1926 |
-
"dev": true,
|
1927 |
-
"optional": true
|
1928 |
-
},
|
1929 |
-
"json-schema-traverse": {
|
1930 |
-
"version": "0.3.1",
|
1931 |
-
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
1932 |
-
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
|
1933 |
-
"dev": true,
|
1934 |
-
"optional": true
|
1935 |
-
},
|
1936 |
-
"json-stringify-safe": {
|
1937 |
-
"version": "5.0.1",
|
1938 |
-
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
1939 |
-
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
1940 |
-
"dev": true,
|
1941 |
-
"optional": true
|
1942 |
-
},
|
1943 |
-
"jsprim": {
|
1944 |
-
"version": "1.4.1",
|
1945 |
-
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
1946 |
-
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
1947 |
-
"dev": true,
|
1948 |
-
"optional": true,
|
1949 |
-
"requires": {
|
1950 |
-
"assert-plus": "1.0.0",
|
1951 |
-
"extsprintf": "1.3.0",
|
1952 |
-
"json-schema": "0.2.3",
|
1953 |
-
"verror": "1.10.0"
|
1954 |
-
}
|
1955 |
-
},
|
1956 |
-
"lazystream": {
|
1957 |
-
"version": "1.0.0",
|
1958 |
-
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
|
1959 |
-
"integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
|
1960 |
-
"dev": true,
|
1961 |
-
"requires": {
|
1962 |
-
"readable-stream": "2.3.3"
|
1963 |
-
}
|
1964 |
-
},
|
1965 |
-
"load-grunt-config": {
|
1966 |
-
"version": "0.19.2",
|
1967 |
-
"resolved": "https://registry.npmjs.org/load-grunt-config/-/load-grunt-config-0.19.2.tgz",
|
1968 |
-
"integrity": "sha1-UgkNSiDG5j90p2SPJJsZ57f87CQ=",
|
1969 |
-
"dev": true,
|
1970 |
-
"requires": {
|
1971 |
-
"cson": "3.0.2",
|
1972 |
-
"glob": "5.0.15",
|
1973 |
-
"jit-grunt": "0.10.0",
|
1974 |
-
"js-yaml": "3.4.6",
|
1975 |
-
"load-grunt-tasks": "3.3.0",
|
1976 |
-
"lodash": "3.10.1"
|
1977 |
-
},
|
1978 |
-
"dependencies": {
|
1979 |
-
"argparse": {
|
1980 |
-
"version": "1.0.9",
|
1981 |
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
|
1982 |
-
"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
|
1983 |
-
"dev": true,
|
1984 |
-
"requires": {
|
1985 |
-
"sprintf-js": "1.0.3"
|
1986 |
-
}
|
1987 |
-
},
|
1988 |
-
"esprima": {
|
1989 |
-
"version": "2.7.3",
|
1990 |
-
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
|
1991 |
-
"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
|
1992 |
-
"dev": true
|
1993 |
-
},
|
1994 |
-
"glob": {
|
1995 |
-
"version": "5.0.15",
|
1996 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
|
1997 |
-
"integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
|
1998 |
-
"dev": true,
|
1999 |
-
"requires": {
|
2000 |
-
"inflight": "1.0.6",
|
2001 |
-
"inherits": "2.0.3",
|
2002 |
-
"minimatch": "3.0.4",
|
2003 |
-
"once": "1.4.0",
|
2004 |
-
"path-is-absolute": "1.0.1"
|
2005 |
-
}
|
2006 |
-
},
|
2007 |
-
"js-yaml": {
|
2008 |
-
"version": "3.4.6",
|
2009 |
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.6.tgz",
|
2010 |
-
"integrity": "sha1-a+GyP2JJ9T0pM3D9TRqqY84bTrA=",
|
2011 |
-
"dev": true,
|
2012 |
-
"requires": {
|
2013 |
-
"argparse": "1.0.9",
|
2014 |
-
"esprima": "2.7.3",
|
2015 |
-
"inherit": "2.2.6"
|
2016 |
-
}
|
2017 |
-
},
|
2018 |
-
"load-grunt-tasks": {
|
2019 |
-
"version": "3.3.0",
|
2020 |
-
"resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.3.0.tgz",
|
2021 |
-
"integrity": "sha1-vliSkJRY2T3fdp60vGhRAggMYyE=",
|
2022 |
-
"dev": true,
|
2023 |
-
"requires": {
|
2024 |
-
"arrify": "1.0.1",
|
2025 |
-
"multimatch": "2.1.0",
|
2026 |
-
"pkg-up": "1.0.0"
|
2027 |
-
}
|
2028 |
-
},
|
2029 |
-
"lodash": {
|
2030 |
-
"version": "3.10.1",
|
2031 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
2032 |
-
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
|
2033 |
-
"dev": true
|
2034 |
-
},
|
2035 |
-
"minimatch": {
|
2036 |
-
"version": "3.0.4",
|
2037 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
2038 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
2039 |
-
"dev": true,
|
2040 |
-
"requires": {
|
2041 |
-
"brace-expansion": "1.1.8"
|
2042 |
-
}
|
2043 |
-
}
|
2044 |
-
}
|
2045 |
-
},
|
2046 |
-
"load-grunt-tasks": {
|
2047 |
-
"version": "3.1.0",
|
2048 |
-
"resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.1.0.tgz",
|
2049 |
-
"integrity": "sha1-9Z56g0E+Loclkcd3f/3BijcJ2iA=",
|
2050 |
-
"dev": true,
|
2051 |
-
"requires": {
|
2052 |
-
"findup-sync": "0.2.1",
|
2053 |
-
"multimatch": "2.1.0"
|
2054 |
-
},
|
2055 |
-
"dependencies": {
|
2056 |
-
"findup-sync": {
|
2057 |
-
"version": "0.2.1",
|
2058 |
-
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz",
|
2059 |
-
"integrity": "sha1-4KkKRQB1xJRm7lE3MgV1FLgeh4w=",
|
2060 |
-
"dev": true,
|
2061 |
-
"requires": {
|
2062 |
-
"glob": "4.3.5"
|
2063 |
-
}
|
2064 |
-
},
|
2065 |
-
"glob": {
|
2066 |
-
"version": "4.3.5",
|
2067 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz",
|
2068 |
-
"integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=",
|
2069 |
-
"dev": true,
|
2070 |
-
"requires": {
|
2071 |
-
"inflight": "1.0.6",
|
2072 |
-
"inherits": "2.0.3",
|
2073 |
-
"minimatch": "2.0.10",
|
2074 |
-
"once": "1.4.0"
|
2075 |
-
}
|
2076 |
-
},
|
2077 |
-
"minimatch": {
|
2078 |
-
"version": "2.0.10",
|
2079 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
|
2080 |
-
"integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=",
|
2081 |
-
"dev": true,
|
2082 |
-
"requires": {
|
2083 |
-
"brace-expansion": "1.1.8"
|
2084 |
-
}
|
2085 |
-
}
|
2086 |
-
}
|
2087 |
-
},
|
2088 |
-
"load-json-file": {
|
2089 |
-
"version": "1.1.0",
|
2090 |
-
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
2091 |
-
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
2092 |
-
"dev": true,
|
2093 |
-
"requires": {
|
2094 |
-
"graceful-fs": "4.1.11",
|
2095 |
-
"parse-json": "2.2.0",
|
2096 |
-
"pify": "2.3.0",
|
2097 |
-
"pinkie-promise": "2.0.1",
|
2098 |
-
"strip-bom": "2.0.0"
|
2099 |
-
},
|
2100 |
-
"dependencies": {
|
2101 |
-
"graceful-fs": {
|
2102 |
-
"version": "4.1.11",
|
2103 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
2104 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
2105 |
-
"dev": true
|
2106 |
-
}
|
2107 |
-
}
|
2108 |
-
},
|
2109 |
-
"lodash": {
|
2110 |
-
"version": "3.10.1",
|
2111 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
2112 |
-
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
|
2113 |
-
"dev": true
|
2114 |
-
},
|
2115 |
-
"loud-rejection": {
|
2116 |
-
"version": "1.6.0",
|
2117 |
-
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
2118 |
-
"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
|
2119 |
-
"dev": true,
|
2120 |
-
"requires": {
|
2121 |
-
"currently-unhandled": "0.4.1",
|
2122 |
-
"signal-exit": "3.0.2"
|
2123 |
-
}
|
2124 |
-
},
|
2125 |
-
"lru-cache": {
|
2126 |
-
"version": "2.7.3",
|
2127 |
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
|
2128 |
-
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
|
2129 |
-
"dev": true
|
2130 |
-
},
|
2131 |
-
"map-obj": {
|
2132 |
-
"version": "1.0.1",
|
2133 |
-
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
|
2134 |
-
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
|
2135 |
-
"dev": true
|
2136 |
-
},
|
2137 |
-
"maxmin": {
|
2138 |
-
"version": "1.1.0",
|
2139 |
-
"resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz",
|
2140 |
-
"integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=",
|
2141 |
-
"dev": true,
|
2142 |
-
"requires": {
|
2143 |
-
"chalk": "1.1.3",
|
2144 |
-
"figures": "1.7.0",
|
2145 |
-
"gzip-size": "1.0.0",
|
2146 |
-
"pretty-bytes": "1.0.4"
|
2147 |
-
},
|
2148 |
-
"dependencies": {
|
2149 |
-
"ansi-regex": {
|
2150 |
-
"version": "2.1.1",
|
2151 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
2152 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
2153 |
-
"dev": true
|
2154 |
-
},
|
2155 |
-
"ansi-styles": {
|
2156 |
-
"version": "2.2.1",
|
2157 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
2158 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
2159 |
-
"dev": true
|
2160 |
-
},
|
2161 |
-
"chalk": {
|
2162 |
-
"version": "1.1.3",
|
2163 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
2164 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
2165 |
-
"dev": true,
|
2166 |
-
"requires": {
|
2167 |
-
"ansi-styles": "2.2.1",
|
2168 |
-
"escape-string-regexp": "1.0.5",
|
2169 |
-
"has-ansi": "2.0.0",
|
2170 |
-
"strip-ansi": "3.0.1",
|
2171 |
-
"supports-color": "2.0.0"
|
2172 |
-
}
|
2173 |
-
},
|
2174 |
-
"has-ansi": {
|
2175 |
-
"version": "2.0.0",
|
2176 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
2177 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
2178 |
-
"dev": true,
|
2179 |
-
"requires": {
|
2180 |
-
"ansi-regex": "2.1.1"
|
2181 |
-
}
|
2182 |
-
},
|
2183 |
-
"strip-ansi": {
|
2184 |
-
"version": "3.0.1",
|
2185 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
2186 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
2187 |
-
"dev": true,
|
2188 |
-
"requires": {
|
2189 |
-
"ansi-regex": "2.1.1"
|
2190 |
-
}
|
2191 |
-
},
|
2192 |
-
"supports-color": {
|
2193 |
-
"version": "2.0.0",
|
2194 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
2195 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
2196 |
-
"dev": true
|
2197 |
-
}
|
2198 |
-
}
|
2199 |
-
},
|
2200 |
-
"meow": {
|
2201 |
-
"version": "3.7.0",
|
2202 |
-
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
|
2203 |
-
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
|
2204 |
-
"dev": true,
|
2205 |
-
"requires": {
|
2206 |
-
"camelcase-keys": "2.1.0",
|
2207 |
-
"decamelize": "1.2.0",
|
2208 |
-
"loud-rejection": "1.6.0",
|
2209 |
-
"map-obj": "1.0.1",
|
2210 |
-
"minimist": "1.2.0",
|
2211 |
-
"normalize-package-data": "2.4.0",
|
2212 |
-
"object-assign": "4.1.1",
|
2213 |
-
"read-pkg-up": "1.0.1",
|
2214 |
-
"redent": "1.0.0",
|
2215 |
-
"trim-newlines": "1.0.0"
|
2216 |
-
}
|
2217 |
-
},
|
2218 |
-
"mime-db": {
|
2219 |
-
"version": "1.30.0",
|
2220 |
-
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
|
2221 |
-
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
|
2222 |
-
"dev": true
|
2223 |
-
},
|
2224 |
-
"mime-types": {
|
2225 |
-
"version": "2.1.17",
|
2226 |
-
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
|
2227 |
-
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
|
2228 |
-
"dev": true,
|
2229 |
-
"requires": {
|
2230 |
-
"mime-db": "1.30.0"
|
2231 |
-
}
|
2232 |
-
},
|
2233 |
-
"minimatch": {
|
2234 |
-
"version": "0.2.14",
|
2235 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
|
2236 |
-
"integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
|
2237 |
-
"dev": true,
|
2238 |
-
"requires": {
|
2239 |
-
"lru-cache": "2.7.3",
|
2240 |
-
"sigmund": "1.0.1"
|
2241 |
-
}
|
2242 |
-
},
|
2243 |
-
"minimist": {
|
2244 |
-
"version": "1.2.0",
|
2245 |
-
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
2246 |
-
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
2247 |
-
"dev": true
|
2248 |
-
},
|
2249 |
-
"mkdirp": {
|
2250 |
-
"version": "0.5.1",
|
2251 |
-
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
2252 |
-
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
2253 |
-
"dev": true,
|
2254 |
-
"requires": {
|
2255 |
-
"minimist": "0.0.8"
|
2256 |
-
},
|
2257 |
-
"dependencies": {
|
2258 |
-
"minimist": {
|
2259 |
-
"version": "0.0.8",
|
2260 |
-
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
2261 |
-
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
2262 |
-
"dev": true
|
2263 |
-
}
|
2264 |
-
}
|
2265 |
-
},
|
2266 |
-
"multimatch": {
|
2267 |
-
"version": "2.1.0",
|
2268 |
-
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
|
2269 |
-
"integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
|
2270 |
-
"dev": true,
|
2271 |
-
"requires": {
|
2272 |
-
"array-differ": "1.0.0",
|
2273 |
-
"array-union": "1.0.2",
|
2274 |
-
"arrify": "1.0.1",
|
2275 |
-
"minimatch": "3.0.4"
|
2276 |
-
},
|
2277 |
-
"dependencies": {
|
2278 |
-
"minimatch": {
|
2279 |
-
"version": "3.0.4",
|
2280 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
2281 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
2282 |
-
"dev": true,
|
2283 |
-
"requires": {
|
2284 |
-
"brace-expansion": "1.1.8"
|
2285 |
-
}
|
2286 |
-
}
|
2287 |
-
}
|
2288 |
-
},
|
2289 |
-
"nan": {
|
2290 |
-
"version": "2.8.0",
|
2291 |
-
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
|
2292 |
-
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
|
2293 |
-
"dev": true,
|
2294 |
-
"optional": true
|
2295 |
-
},
|
2296 |
-
"node-abi": {
|
2297 |
-
"version": "2.1.2",
|
2298 |
-
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.1.2.tgz",
|
2299 |
-
"integrity": "sha512-hmUtb8m75RSi7N+zZLYqe75XDvZB+6LyTBPkj2DConvNgQet2e3BIqEwe1LLvqMrfyjabuT5ZOrTioLCH1HTdA==",
|
2300 |
-
"dev": true,
|
2301 |
-
"optional": true,
|
2302 |
-
"requires": {
|
2303 |
-
"semver": "5.4.1"
|
2304 |
-
}
|
2305 |
-
},
|
2306 |
-
"node-gyp": {
|
2307 |
-
"version": "3.6.2",
|
2308 |
-
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
|
2309 |
-
"integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=",
|
2310 |
-
"dev": true,
|
2311 |
-
"optional": true,
|
2312 |
-
"requires": {
|
2313 |
-
"fstream": "1.0.11",
|
2314 |
-
"glob": "7.1.2",
|
2315 |
-
"graceful-fs": "4.1.11",
|
2316 |
-
"minimatch": "3.0.4",
|
2317 |
-
"mkdirp": "0.5.1",
|
2318 |
-
"nopt": "3.0.6",
|
2319 |
-
"npmlog": "4.1.2",
|
2320 |
-
"osenv": "0.1.4",
|
2321 |
-
"request": "2.83.0",
|
2322 |
-
"rimraf": "2.2.8",
|
2323 |
-
"semver": "5.3.0",
|
2324 |
-
"tar": "2.2.1",
|
2325 |
-
"which": "1.2.14"
|
2326 |
-
},
|
2327 |
-
"dependencies": {
|
2328 |
-
"glob": {
|
2329 |
-
"version": "7.1.2",
|
2330 |
-
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
2331 |
-
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
2332 |
-
"dev": true,
|
2333 |
-
"optional": true,
|
2334 |
-
"requires": {
|
2335 |
-
"fs.realpath": "1.0.0",
|
2336 |
-
"inflight": "1.0.6",
|
2337 |
-
"inherits": "2.0.3",
|
2338 |
-
"minimatch": "3.0.4",
|
2339 |
-
"once": "1.4.0",
|
2340 |
-
"path-is-absolute": "1.0.1"
|
2341 |
-
}
|
2342 |
-
},
|
2343 |
-
"graceful-fs": {
|
2344 |
-
"version": "4.1.11",
|
2345 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
2346 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
2347 |
-
"dev": true,
|
2348 |
-
"optional": true
|
2349 |
-
},
|
2350 |
-
"minimatch": {
|
2351 |
-
"version": "3.0.4",
|
2352 |
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
2353 |
-
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
2354 |
-
"dev": true,
|
2355 |
-
"requires": {
|
2356 |
-
"brace-expansion": "1.1.8"
|
2357 |
-
}
|
2358 |
-
},
|
2359 |
-
"semver": {
|
2360 |
-
"version": "5.3.0",
|
2361 |
-
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
2362 |
-
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
|
2363 |
-
"dev": true,
|
2364 |
-
"optional": true
|
2365 |
-
}
|
2366 |
-
}
|
2367 |
-
},
|
2368 |
-
"noop-logger": {
|
2369 |
-
"version": "0.1.1",
|
2370 |
-
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
|
2371 |
-
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
|
2372 |
-
"dev": true,
|
2373 |
-
"optional": true
|
2374 |
-
},
|
2375 |
-
"nopt": {
|
2376 |
-
"version": "3.0.6",
|
2377 |
-
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
2378 |
-
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
|
2379 |
-
"dev": true,
|
2380 |
-
"requires": {
|
2381 |
-
"abbrev": "1.1.1"
|
2382 |
-
}
|
2383 |
-
},
|
2384 |
-
"normalize-package-data": {
|
2385 |
-
"version": "2.4.0",
|
2386 |
-
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
2387 |
-
"integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
|
2388 |
-
"dev": true,
|
2389 |
-
"requires": {
|
2390 |
-
"hosted-git-info": "2.5.0",
|
2391 |
-
"is-builtin-module": "1.0.0",
|
2392 |
-
"semver": "5.4.1",
|
2393 |
-
"validate-npm-package-license": "3.0.1"
|
2394 |
-
}
|
2395 |
-
},
|
2396 |
-
"normalize-path": {
|
2397 |
-
"version": "2.1.1",
|
2398 |
-
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
|
2399 |
-
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
|
2400 |
-
"dev": true,
|
2401 |
-
"requires": {
|
2402 |
-
"remove-trailing-separator": "1.1.0"
|
2403 |
-
}
|
2404 |
-
},
|
2405 |
-
"npmlog": {
|
2406 |
-
"version": "4.1.2",
|
2407 |
-
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
2408 |
-
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
2409 |
-
"dev": true,
|
2410 |
-
"requires": {
|
2411 |
-
"are-we-there-yet": "1.1.4",
|
2412 |
-
"console-control-strings": "1.1.0",
|
2413 |
-
"gauge": "2.7.4",
|
2414 |
-
"set-blocking": "2.0.0"
|
2415 |
-
}
|
2416 |
-
},
|
2417 |
-
"number-is-nan": {
|
2418 |
-
"version": "1.0.1",
|
2419 |
-
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
2420 |
-
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
2421 |
-
"dev": true
|
2422 |
-
},
|
2423 |
-
"oauth-sign": {
|
2424 |
-
"version": "0.8.2",
|
2425 |
-
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
2426 |
-
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
|
2427 |
-
"dev": true,
|
2428 |
-
"optional": true
|
2429 |
-
},
|
2430 |
-
"object-assign": {
|
2431 |
-
"version": "4.1.1",
|
2432 |
-
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
2433 |
-
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
2434 |
-
"dev": true
|
2435 |
-
},
|
2436 |
-
"once": {
|
2437 |
-
"version": "1.4.0",
|
2438 |
-
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
2439 |
-
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
2440 |
-
"dev": true,
|
2441 |
-
"requires": {
|
2442 |
-
"wrappy": "1.0.2"
|
2443 |
-
}
|
2444 |
-
},
|
2445 |
-
"os-homedir": {
|
2446 |
-
"version": "1.0.2",
|
2447 |
-
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
2448 |
-
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
2449 |
-
"dev": true
|
2450 |
-
},
|
2451 |
-
"os-tmpdir": {
|
2452 |
-
"version": "1.0.2",
|
2453 |
-
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
2454 |
-
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
2455 |
-
"dev": true,
|
2456 |
-
"optional": true
|
2457 |
-
},
|
2458 |
-
"osenv": {
|
2459 |
-
"version": "0.1.4",
|
2460 |
-
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
|
2461 |
-
"integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
|
2462 |
-
"dev": true,
|
2463 |
-
"optional": true,
|
2464 |
-
"requires": {
|
2465 |
-
"os-homedir": "1.0.2",
|
2466 |
-
"os-tmpdir": "1.0.2"
|
2467 |
-
}
|
2468 |
-
},
|
2469 |
-
"pako": {
|
2470 |
-
"version": "0.2.9",
|
2471 |
-
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
2472 |
-
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
|
2473 |
-
"dev": true
|
2474 |
-
},
|
2475 |
-
"parse-json": {
|
2476 |
-
"version": "2.2.0",
|
2477 |
-
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
|
2478 |
-
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
|
2479 |
-
"dev": true,
|
2480 |
-
"requires": {
|
2481 |
-
"error-ex": "1.3.1"
|
2482 |
-
}
|
2483 |
-
},
|
2484 |
-
"parse-ms": {
|
2485 |
-
"version": "1.0.1",
|
2486 |
-
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz",
|
2487 |
-
"integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=",
|
2488 |
-
"dev": true
|
2489 |
-
},
|
2490 |
-
"path-exists": {
|
2491 |
-
"version": "2.1.0",
|
2492 |
-
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
|
2493 |
-
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
|
2494 |
-
"dev": true,
|
2495 |
-
"requires": {
|
2496 |
-
"pinkie-promise": "2.0.1"
|
2497 |
-
}
|
2498 |
-
},
|
2499 |
-
"path-is-absolute": {
|
2500 |
-
"version": "1.0.1",
|
2501 |
-
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
2502 |
-
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
2503 |
-
"dev": true
|
2504 |
-
},
|
2505 |
-
"path-type": {
|
2506 |
-
"version": "1.1.0",
|
2507 |
-
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
|
2508 |
-
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
|
2509 |
-
"dev": true,
|
2510 |
-
"requires": {
|
2511 |
-
"graceful-fs": "4.1.11",
|
2512 |
-
"pify": "2.3.0",
|
2513 |
-
"pinkie-promise": "2.0.1"
|
2514 |
-
},
|
2515 |
-
"dependencies": {
|
2516 |
-
"graceful-fs": {
|
2517 |
-
"version": "4.1.11",
|
2518 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
2519 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
2520 |
-
"dev": true
|
2521 |
-
}
|
2522 |
-
}
|
2523 |
-
},
|
2524 |
-
"performance-now": {
|
2525 |
-
"version": "2.1.0",
|
2526 |
-
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
2527 |
-
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
2528 |
-
"dev": true,
|
2529 |
-
"optional": true
|
2530 |
-
},
|
2531 |
-
"pify": {
|
2532 |
-
"version": "2.3.0",
|
2533 |
-
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
2534 |
-
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
2535 |
-
"dev": true
|
2536 |
-
},
|
2537 |
-
"pinkie": {
|
2538 |
-
"version": "2.0.4",
|
2539 |
-
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
2540 |
-
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
|
2541 |
-
"dev": true
|
2542 |
-
},
|
2543 |
-
"pinkie-promise": {
|
2544 |
-
"version": "2.0.1",
|
2545 |
-
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
2546 |
-
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
2547 |
-
"dev": true,
|
2548 |
-
"requires": {
|
2549 |
-
"pinkie": "2.0.4"
|
2550 |
-
}
|
2551 |
-
},
|
2552 |
-
"pkg-up": {
|
2553 |
-
"version": "1.0.0",
|
2554 |
-
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz",
|
2555 |
-
"integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=",
|
2556 |
-
"dev": true,
|
2557 |
-
"requires": {
|
2558 |
-
"find-up": "1.1.2"
|
2559 |
-
}
|
2560 |
-
},
|
2561 |
-
"plur": {
|
2562 |
-
"version": "1.0.0",
|
2563 |
-
"resolved": "https://registry.npmjs.org/plur/-/plur-1.0.0.tgz",
|
2564 |
-
"integrity": "sha1-24XGgU9eXlo7Se/CjWBP7GKXUVY=",
|
2565 |
-
"dev": true
|
2566 |
-
},
|
2567 |
-
"prebuild-install": {
|
2568 |
-
"version": "2.4.1",
|
2569 |
-
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.4.1.tgz",
|
2570 |
-
"integrity": "sha512-99TyEFYTTkBWANT+mwSptmLb9ZCLQ6qKIUE36fXSIOtShB0JNprL2hzBD8F1yIuT9btjFrFEwbRHXhqDi1HmRA==",
|
2571 |
-
"dev": true,
|
2572 |
-
"optional": true,
|
2573 |
-
"requires": {
|
2574 |
-
"expand-template": "1.1.0",
|
2575 |
-
"github-from-package": "0.0.0",
|
2576 |
-
"minimist": "1.2.0",
|
2577 |
-
"mkdirp": "0.5.1",
|
2578 |
-
"node-abi": "2.1.2",
|
2579 |
-
"noop-logger": "0.1.1",
|
2580 |
-
"npmlog": "4.1.2",
|
2581 |
-
"os-homedir": "1.0.2",
|
2582 |
-
"pump": "1.0.3",
|
2583 |
-
"rc": "1.2.2",
|
2584 |
-
"simple-get": "1.4.3",
|
2585 |
-
"tar-fs": "1.16.0",
|
2586 |
-
"tunnel-agent": "0.6.0",
|
2587 |
-
"xtend": "4.0.1"
|
2588 |
-
}
|
2589 |
-
},
|
2590 |
-
"pretty-bytes": {
|
2591 |
-
"version": "1.0.4",
|
2592 |
-
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
|
2593 |
-
"integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
|
2594 |
-
"dev": true,
|
2595 |
-
"requires": {
|
2596 |
-
"get-stdin": "4.0.1",
|
2597 |
-
"meow": "3.7.0"
|
2598 |
-
}
|
2599 |
-
},
|
2600 |
-
"pretty-ms": {
|
2601 |
-
"version": "1.4.0",
|
2602 |
-
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-1.4.0.tgz",
|
2603 |
-
"integrity": "sha1-aQ1VY3lXwMU/gIaoEK23R4Jamg8=",
|
2604 |
-
"dev": true,
|
2605 |
-
"requires": {
|
2606 |
-
"get-stdin": "4.0.1",
|
2607 |
-
"is-finite": "1.0.2",
|
2608 |
-
"meow": "3.7.0",
|
2609 |
-
"parse-ms": "1.0.1",
|
2610 |
-
"plur": "1.0.0"
|
2611 |
-
}
|
2612 |
-
},
|
2613 |
-
"process-nextick-args": {
|
2614 |
-
"version": "1.0.7",
|
2615 |
-
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
2616 |
-
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
|
2617 |
-
"dev": true
|
2618 |
-
},
|
2619 |
-
"pump": {
|
2620 |
-
"version": "1.0.3",
|
2621 |
-
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
|
2622 |
-
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
|
2623 |
-
"dev": true,
|
2624 |
-
"requires": {
|
2625 |
-
"end-of-stream": "1.4.0",
|
2626 |
-
"once": "1.4.0"
|
2627 |
-
}
|
2628 |
-
},
|
2629 |
-
"punycode": {
|
2630 |
-
"version": "1.4.1",
|
2631 |
-
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
2632 |
-
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
2633 |
-
"dev": true,
|
2634 |
-
"optional": true
|
2635 |
-
},
|
2636 |
-
"qs": {
|
2637 |
-
"version": "6.5.1",
|
2638 |
-
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
2639 |
-
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
|
2640 |
-
"dev": true,
|
2641 |
-
"optional": true
|
2642 |
-
},
|
2643 |
-
"rc": {
|
2644 |
-
"version": "1.2.2",
|
2645 |
-
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz",
|
2646 |
-
"integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=",
|
2647 |
-
"dev": true,
|
2648 |
-
"optional": true,
|
2649 |
-
"requires": {
|
2650 |
-
"deep-extend": "0.4.2",
|
2651 |
-
"ini": "1.3.5",
|
2652 |
-
"minimist": "1.2.0",
|
2653 |
-
"strip-json-comments": "2.0.1"
|
2654 |
-
}
|
2655 |
-
},
|
2656 |
-
"read-pkg": {
|
2657 |
-
"version": "1.1.0",
|
2658 |
-
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
2659 |
-
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
|
2660 |
-
"dev": true,
|
2661 |
-
"requires": {
|
2662 |
-
"load-json-file": "1.1.0",
|
2663 |
-
"normalize-package-data": "2.4.0",
|
2664 |
-
"path-type": "1.1.0"
|
2665 |
-
}
|
2666 |
-
},
|
2667 |
-
"read-pkg-up": {
|
2668 |
-
"version": "1.0.1",
|
2669 |
-
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
|
2670 |
-
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
|
2671 |
-
"dev": true,
|
2672 |
-
"requires": {
|
2673 |
-
"find-up": "1.1.2",
|
2674 |
-
"read-pkg": "1.1.0"
|
2675 |
-
}
|
2676 |
-
},
|
2677 |
-
"readable-stream": {
|
2678 |
-
"version": "2.3.3",
|
2679 |
-
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
2680 |
-
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
|
2681 |
-
"dev": true,
|
2682 |
-
"requires": {
|
2683 |
-
"core-util-is": "1.0.2",
|
2684 |
-
"inherits": "2.0.3",
|
2685 |
-
"isarray": "1.0.0",
|
2686 |
-
"process-nextick-args": "1.0.7",
|
2687 |
-
"safe-buffer": "5.1.1",
|
2688 |
-
"string_decoder": "1.0.3",
|
2689 |
-
"util-deprecate": "1.0.2"
|
2690 |
-
}
|
2691 |
-
},
|
2692 |
-
"redent": {
|
2693 |
-
"version": "1.0.0",
|
2694 |
-
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
|
2695 |
-
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
|
2696 |
-
"dev": true,
|
2697 |
-
"requires": {
|
2698 |
-
"indent-string": "2.1.0",
|
2699 |
-
"strip-indent": "1.0.1"
|
2700 |
-
}
|
2701 |
-
},
|
2702 |
-
"remove-trailing-separator": {
|
2703 |
-
"version": "1.1.0",
|
2704 |
-
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
2705 |
-
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
|
2706 |
-
"dev": true
|
2707 |
-
},
|
2708 |
-
"repeating": {
|
2709 |
-
"version": "2.0.1",
|
2710 |
-
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
|
2711 |
-
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
|
2712 |
-
"dev": true,
|
2713 |
-
"requires": {
|
2714 |
-
"is-finite": "1.0.2"
|
2715 |
-
}
|
2716 |
-
},
|
2717 |
-
"request": {
|
2718 |
-
"version": "2.83.0",
|
2719 |
-
"resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz",
|
2720 |
-
"integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==",
|
2721 |
-
"dev": true,
|
2722 |
-
"optional": true,
|
2723 |
-
"requires": {
|
2724 |
-
"aws-sign2": "0.7.0",
|
2725 |
-
"aws4": "1.6.0",
|
2726 |
-
"caseless": "0.12.0",
|
2727 |
-
"combined-stream": "1.0.5",
|
2728 |
-
"extend": "3.0.1",
|
2729 |
-
"forever-agent": "0.6.1",
|
2730 |
-
"form-data": "2.3.1",
|
2731 |
-
"har-validator": "5.0.3",
|
2732 |
-
"hawk": "6.0.2",
|
2733 |
-
"http-signature": "1.2.0",
|
2734 |
-
"is-typedarray": "1.0.0",
|
2735 |
-
"isstream": "0.1.2",
|
2736 |
-
"json-stringify-safe": "5.0.1",
|
2737 |
-
"mime-types": "2.1.17",
|
2738 |
-
"oauth-sign": "0.8.2",
|
2739 |
-
"performance-now": "2.1.0",
|
2740 |
-
"qs": "6.5.1",
|
2741 |
-
"safe-buffer": "5.1.1",
|
2742 |
-
"stringstream": "0.0.5",
|
2743 |
-
"tough-cookie": "2.3.3",
|
2744 |
-
"tunnel-agent": "0.6.0",
|
2745 |
-
"uuid": "3.1.0"
|
2746 |
-
}
|
2747 |
-
},
|
2748 |
-
"requirefresh": {
|
2749 |
-
"version": "2.1.0",
|
2750 |
-
"resolved": "https://registry.npmjs.org/requirefresh/-/requirefresh-2.1.0.tgz",
|
2751 |
-
"integrity": "sha1-dC3Mwg86lpGNZsbxWX3I/+vE9vU=",
|
2752 |
-
"dev": true,
|
2753 |
-
"requires": {
|
2754 |
-
"editions": "1.3.3"
|
2755 |
-
}
|
2756 |
-
},
|
2757 |
-
"resolve": {
|
2758 |
-
"version": "1.1.7",
|
2759 |
-
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
2760 |
-
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
|
2761 |
-
"dev": true
|
2762 |
-
},
|
2763 |
-
"rimraf": {
|
2764 |
-
"version": "2.2.8",
|
2765 |
-
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
2766 |
-
"integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
|
2767 |
-
"dev": true
|
2768 |
-
},
|
2769 |
-
"safe-buffer": {
|
2770 |
-
"version": "5.1.1",
|
2771 |
-
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
2772 |
-
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
2773 |
-
"dev": true
|
2774 |
-
},
|
2775 |
-
"safefs": {
|
2776 |
-
"version": "4.1.0",
|
2777 |
-
"resolved": "https://registry.npmjs.org/safefs/-/safefs-4.1.0.tgz",
|
2778 |
-
"integrity": "sha1-+CrrS9165R9lPrIPZyizBYyNZEU=",
|
2779 |
-
"dev": true,
|
2780 |
-
"requires": {
|
2781 |
-
"editions": "1.3.3",
|
2782 |
-
"graceful-fs": "4.1.11"
|
2783 |
-
},
|
2784 |
-
"dependencies": {
|
2785 |
-
"graceful-fs": {
|
2786 |
-
"version": "4.1.11",
|
2787 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
2788 |
-
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
2789 |
-
"dev": true
|
2790 |
-
}
|
2791 |
-
}
|
2792 |
-
},
|
2793 |
-
"semver": {
|
2794 |
-
"version": "5.4.1",
|
2795 |
-
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
2796 |
-
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
2797 |
-
"dev": true
|
2798 |
-
},
|
2799 |
-
"set-blocking": {
|
2800 |
-
"version": "2.0.0",
|
2801 |
-
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
2802 |
-
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
2803 |
-
"dev": true
|
2804 |
-
},
|
2805 |
-
"shelljs": {
|
2806 |
-
"version": "0.1.4",
|
2807 |
-
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz",
|
2808 |
-
"integrity": "sha1-37vnjVbDwBaNL7eeEOzR28sH7A4=",
|
2809 |
-
"dev": true
|
2810 |
-
},
|
2811 |
-
"sigmund": {
|
2812 |
-
"version": "1.0.1",
|
2813 |
-
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
|
2814 |
-
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
|
2815 |
-
"dev": true
|
2816 |
-
},
|
2817 |
-
"signal-exit": {
|
2818 |
-
"version": "3.0.2",
|
2819 |
-
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
2820 |
-
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
2821 |
-
"dev": true
|
2822 |
-
},
|
2823 |
-
"simple-get": {
|
2824 |
-
"version": "1.4.3",
|
2825 |
-
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz",
|
2826 |
-
"integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=",
|
2827 |
-
"dev": true,
|
2828 |
-
"optional": true,
|
2829 |
-
"requires": {
|
2830 |
-
"once": "1.4.0",
|
2831 |
-
"unzip-response": "1.0.2",
|
2832 |
-
"xtend": "4.0.1"
|
2833 |
-
}
|
2834 |
-
},
|
2835 |
-
"sntp": {
|
2836 |
-
"version": "2.1.0",
|
2837 |
-
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
|
2838 |
-
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
|
2839 |
-
"dev": true,
|
2840 |
-
"optional": true,
|
2841 |
-
"requires": {
|
2842 |
-
"hoek": "4.2.0"
|
2843 |
-
}
|
2844 |
-
},
|
2845 |
-
"source-map": {
|
2846 |
-
"version": "0.4.4",
|
2847 |
-
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
2848 |
-
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
2849 |
-
"dev": true,
|
2850 |
-
"requires": {
|
2851 |
-
"amdefine": "1.0.1"
|
2852 |
-
}
|
2853 |
-
},
|
2854 |
-
"spdx-correct": {
|
2855 |
-
"version": "1.0.2",
|
2856 |
-
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
|
2857 |
-
"integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
|
2858 |
-
"dev": true,
|
2859 |
-
"requires": {
|
2860 |
-
"spdx-license-ids": "1.2.2"
|
2861 |
-
}
|
2862 |
-
},
|
2863 |
-
"spdx-expression-parse": {
|
2864 |
-
"version": "1.0.4",
|
2865 |
-
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
|
2866 |
-
"integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
|
2867 |
-
"dev": true
|
2868 |
-
},
|
2869 |
-
"spdx-license-ids": {
|
2870 |
-
"version": "1.2.2",
|
2871 |
-
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
|
2872 |
-
"integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
|
2873 |
-
"dev": true
|
2874 |
-
},
|
2875 |
-
"sprintf-js": {
|
2876 |
-
"version": "1.0.3",
|
2877 |
-
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
2878 |
-
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
2879 |
-
"dev": true
|
2880 |
-
},
|
2881 |
-
"sshpk": {
|
2882 |
-
"version": "1.13.1",
|
2883 |
-
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
|
2884 |
-
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
|
2885 |
-
"dev": true,
|
2886 |
-
"optional": true,
|
2887 |
-
"requires": {
|
2888 |
-
"asn1": "0.2.3",
|
2889 |
-
"assert-plus": "1.0.0",
|
2890 |
-
"bcrypt-pbkdf": "1.0.1",
|
2891 |
-
"dashdash": "1.14.1",
|
2892 |
-
"ecc-jsbn": "0.1.1",
|
2893 |
-
"getpass": "0.1.7",
|
2894 |
-
"jsbn": "0.1.1",
|
2895 |
-
"tweetnacl": "0.14.5"
|
2896 |
-
}
|
2897 |
-
},
|
2898 |
-
"stream-buffers": {
|
2899 |
-
"version": "2.2.0",
|
2900 |
-
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
|
2901 |
-
"integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=",
|
2902 |
-
"dev": true
|
2903 |
-
},
|
2904 |
-
"string-width": {
|
2905 |
-
"version": "1.0.2",
|
2906 |
-
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
2907 |
-
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
2908 |
-
"dev": true,
|
2909 |
-
"requires": {
|
2910 |
-
"code-point-at": "1.1.0",
|
2911 |
-
"is-fullwidth-code-point": "1.0.0",
|
2912 |
-
"strip-ansi": "3.0.1"
|
2913 |
-
},
|
2914 |
-
"dependencies": {
|
2915 |
-
"ansi-regex": {
|
2916 |
-
"version": "2.1.1",
|
2917 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
2918 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
2919 |
-
"dev": true
|
2920 |
-
},
|
2921 |
-
"strip-ansi": {
|
2922 |
-
"version": "3.0.1",
|
2923 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
2924 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
2925 |
-
"dev": true,
|
2926 |
-
"requires": {
|
2927 |
-
"ansi-regex": "2.1.1"
|
2928 |
-
}
|
2929 |
-
}
|
2930 |
-
}
|
2931 |
-
},
|
2932 |
-
"string_decoder": {
|
2933 |
-
"version": "1.0.3",
|
2934 |
-
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
2935 |
-
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
2936 |
-
"dev": true,
|
2937 |
-
"requires": {
|
2938 |
-
"safe-buffer": "5.1.1"
|
2939 |
-
}
|
2940 |
-
},
|
2941 |
-
"stringstream": {
|
2942 |
-
"version": "0.0.5",
|
2943 |
-
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
2944 |
-
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
|
2945 |
-
"dev": true,
|
2946 |
-
"optional": true
|
2947 |
-
},
|
2948 |
-
"strip-ansi": {
|
2949 |
-
"version": "0.3.0",
|
2950 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
|
2951 |
-
"integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
|
2952 |
-
"dev": true,
|
2953 |
-
"requires": {
|
2954 |
-
"ansi-regex": "0.2.1"
|
2955 |
-
}
|
2956 |
-
},
|
2957 |
-
"strip-bom": {
|
2958 |
-
"version": "2.0.0",
|
2959 |
-
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
2960 |
-
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
|
2961 |
-
"dev": true,
|
2962 |
-
"requires": {
|
2963 |
-
"is-utf8": "0.2.1"
|
2964 |
-
}
|
2965 |
-
},
|
2966 |
-
"strip-indent": {
|
2967 |
-
"version": "1.0.1",
|
2968 |
-
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
|
2969 |
-
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
|
2970 |
-
"dev": true,
|
2971 |
-
"requires": {
|
2972 |
-
"get-stdin": "4.0.1"
|
2973 |
-
}
|
2974 |
-
},
|
2975 |
-
"strip-json-comments": {
|
2976 |
-
"version": "2.0.1",
|
2977 |
-
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
2978 |
-
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
2979 |
-
"dev": true,
|
2980 |
-
"optional": true
|
2981 |
-
},
|
2982 |
-
"supports-color": {
|
2983 |
-
"version": "0.2.0",
|
2984 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
|
2985 |
-
"integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
|
2986 |
-
"dev": true
|
2987 |
-
},
|
2988 |
-
"tar": {
|
2989 |
-
"version": "2.2.1",
|
2990 |
-
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
|
2991 |
-
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
|
2992 |
-
"dev": true,
|
2993 |
-
"optional": true,
|
2994 |
-
"requires": {
|
2995 |
-
"block-stream": "0.0.9",
|
2996 |
-
"fstream": "1.0.11",
|
2997 |
-
"inherits": "2.0.3"
|
2998 |
-
}
|
2999 |
-
},
|
3000 |
-
"tar-fs": {
|
3001 |
-
"version": "1.16.0",
|
3002 |
-
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz",
|
3003 |
-
"integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==",
|
3004 |
-
"dev": true,
|
3005 |
-
"optional": true,
|
3006 |
-
"requires": {
|
3007 |
-
"chownr": "1.0.1",
|
3008 |
-
"mkdirp": "0.5.1",
|
3009 |
-
"pump": "1.0.3",
|
3010 |
-
"tar-stream": "1.5.5"
|
3011 |
-
}
|
3012 |
-
},
|
3013 |
-
"tar-stream": {
|
3014 |
-
"version": "1.5.5",
|
3015 |
-
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
|
3016 |
-
"integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
|
3017 |
-
"dev": true,
|
3018 |
-
"requires": {
|
3019 |
-
"bl": "1.2.1",
|
3020 |
-
"end-of-stream": "1.4.0",
|
3021 |
-
"readable-stream": "2.3.3",
|
3022 |
-
"xtend": "4.0.1"
|
3023 |
-
}
|
3024 |
-
},
|
3025 |
-
"text-table": {
|
3026 |
-
"version": "0.2.0",
|
3027 |
-
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
3028 |
-
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
3029 |
-
"dev": true
|
3030 |
-
},
|
3031 |
-
"time-grunt": {
|
3032 |
-
"version": "1.1.1",
|
3033 |
-
"resolved": "https://registry.npmjs.org/time-grunt/-/time-grunt-1.1.1.tgz",
|
3034 |
-
"integrity": "sha1-8YW6AAkdu+xmY6Y2cKqr+OcXlM8=",
|
3035 |
-
"dev": true,
|
3036 |
-
"requires": {
|
3037 |
-
"chalk": "1.1.3",
|
3038 |
-
"date-time": "1.1.0",
|
3039 |
-
"figures": "1.7.0",
|
3040 |
-
"hooker": "0.2.3",
|
3041 |
-
"pretty-ms": "1.4.0",
|
3042 |
-
"text-table": "0.2.0"
|
3043 |
-
},
|
3044 |
-
"dependencies": {
|
3045 |
-
"ansi-regex": {
|
3046 |
-
"version": "2.1.1",
|
3047 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
3048 |
-
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
3049 |
-
"dev": true
|
3050 |
-
},
|
3051 |
-
"ansi-styles": {
|
3052 |
-
"version": "2.2.1",
|
3053 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
3054 |
-
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
3055 |
-
"dev": true
|
3056 |
-
},
|
3057 |
-
"chalk": {
|
3058 |
-
"version": "1.1.3",
|
3059 |
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
3060 |
-
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
3061 |
-
"dev": true,
|
3062 |
-
"requires": {
|
3063 |
-
"ansi-styles": "2.2.1",
|
3064 |
-
"escape-string-regexp": "1.0.5",
|
3065 |
-
"has-ansi": "2.0.0",
|
3066 |
-
"strip-ansi": "3.0.1",
|
3067 |
-
"supports-color": "2.0.0"
|
3068 |
-
}
|
3069 |
-
},
|
3070 |
-
"has-ansi": {
|
3071 |
-
"version": "2.0.0",
|
3072 |
-
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
3073 |
-
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
3074 |
-
"dev": true,
|
3075 |
-
"requires": {
|
3076 |
-
"ansi-regex": "2.1.1"
|
3077 |
-
}
|
3078 |
-
},
|
3079 |
-
"strip-ansi": {
|
3080 |
-
"version": "3.0.1",
|
3081 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
3082 |
-
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
3083 |
-
"dev": true,
|
3084 |
-
"requires": {
|
3085 |
-
"ansi-regex": "2.1.1"
|
3086 |
-
}
|
3087 |
-
},
|
3088 |
-
"supports-color": {
|
3089 |
-
"version": "2.0.0",
|
3090 |
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
3091 |
-
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
3092 |
-
"dev": true
|
3093 |
-
}
|
3094 |
-
}
|
3095 |
-
},
|
3096 |
-
"time-zone": {
|
3097 |
-
"version": "0.1.0",
|
3098 |
-
"resolved": "https://registry.npmjs.org/time-zone/-/time-zone-0.1.0.tgz",
|
3099 |
-
"integrity": "sha1-Sncotqwo2w4Aj1FAQ/1VW9VXO0Y=",
|
3100 |
-
"dev": true
|
3101 |
-
},
|
3102 |
-
"tough-cookie": {
|
3103 |
-
"version": "2.3.3",
|
3104 |
-
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
|
3105 |
-
"integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
|
3106 |
-
"dev": true,
|
3107 |
-
"optional": true,
|
3108 |
-
"requires": {
|
3109 |
-
"punycode": "1.4.1"
|
3110 |
-
}
|
3111 |
-
},
|
3112 |
-
"trim-newlines": {
|
3113 |
-
"version": "1.0.0",
|
3114 |
-
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
|
3115 |
-
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
|
3116 |
-
"dev": true
|
3117 |
-
},
|
3118 |
-
"tunnel-agent": {
|
3119 |
-
"version": "0.6.0",
|
3120 |
-
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
3121 |
-
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
3122 |
-
"dev": true,
|
3123 |
-
"requires": {
|
3124 |
-
"safe-buffer": "5.1.1"
|
3125 |
-
}
|
3126 |
-
},
|
3127 |
-
"tweetnacl": {
|
3128 |
-
"version": "0.14.5",
|
3129 |
-
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
3130 |
-
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
3131 |
-
"dev": true,
|
3132 |
-
"optional": true
|
3133 |
-
},
|
3134 |
-
"typechecker": {
|
3135 |
-
"version": "4.4.1",
|
3136 |
-
"resolved": "https://registry.npmjs.org/typechecker/-/typechecker-4.4.1.tgz",
|
3137 |
-
"integrity": "sha1-+XuV9RsDhBchLWd9RaNz7nvO1+Y=",
|
3138 |
-
"dev": true,
|
3139 |
-
"requires": {
|
3140 |
-
"editions": "1.3.3"
|
3141 |
-
}
|
3142 |
-
},
|
3143 |
-
"typedarray": {
|
3144 |
-
"version": "0.0.6",
|
3145 |
-
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
3146 |
-
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
3147 |
-
"dev": true
|
3148 |
-
},
|
3149 |
-
"uglify-js": {
|
3150 |
-
"version": "2.4.24",
|
3151 |
-
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz",
|
3152 |
-
"integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=",
|
3153 |
-
"dev": true,
|
3154 |
-
"requires": {
|
3155 |
-
"async": "0.2.10",
|
3156 |
-
"source-map": "0.1.34",
|
3157 |
-
"uglify-to-browserify": "1.0.2",
|
3158 |
-
"yargs": "3.5.4"
|
3159 |
-
},
|
3160 |
-
"dependencies": {
|
3161 |
-
"async": {
|
3162 |
-
"version": "0.2.10",
|
3163 |
-
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
3164 |
-
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
|
3165 |
-
"dev": true
|
3166 |
-
},
|
3167 |
-
"source-map": {
|
3168 |
-
"version": "0.1.34",
|
3169 |
-
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
|
3170 |
-
"integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=",
|
3171 |
-
"dev": true,
|
3172 |
-
"requires": {
|
3173 |
-
"amdefine": "1.0.1"
|
3174 |
-
}
|
3175 |
-
}
|
3176 |
-
}
|
3177 |
-
},
|
3178 |
-
"uglify-to-browserify": {
|
3179 |
-
"version": "1.0.2",
|
3180 |
-
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
|
3181 |
-
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
|
3182 |
-
"dev": true
|
3183 |
-
},
|
3184 |
-
"underscore": {
|
3185 |
-
"version": "1.7.0",
|
3186 |
-
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
|
3187 |
-
"integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=",
|
3188 |
-
"dev": true
|
3189 |
-
},
|
3190 |
-
"underscore.string": {
|
3191 |
-
"version": "3.2.3",
|
3192 |
-
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
|
3193 |
-
"integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=",
|
3194 |
-
"dev": true
|
3195 |
-
},
|
3196 |
-
"unzip-response": {
|
3197 |
-
"version": "1.0.2",
|
3198 |
-
"resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz",
|
3199 |
-
"integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=",
|
3200 |
-
"dev": true,
|
3201 |
-
"optional": true
|
3202 |
-
},
|
3203 |
-
"util-deprecate": {
|
3204 |
-
"version": "1.0.2",
|
3205 |
-
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
3206 |
-
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
3207 |
-
"dev": true
|
3208 |
-
},
|
3209 |
-
"uuid": {
|
3210 |
-
"version": "3.1.0",
|
3211 |
-
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
|
3212 |
-
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==",
|
3213 |
-
"dev": true,
|
3214 |
-
"optional": true
|
3215 |
-
},
|
3216 |
-
"validate-npm-package-license": {
|
3217 |
-
"version": "3.0.1",
|
3218 |
-
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
|
3219 |
-
"integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
|
3220 |
-
"dev": true,
|
3221 |
-
"requires": {
|
3222 |
-
"spdx-correct": "1.0.2",
|
3223 |
-
"spdx-expression-parse": "1.0.4"
|
3224 |
-
}
|
3225 |
-
},
|
3226 |
-
"verror": {
|
3227 |
-
"version": "1.10.0",
|
3228 |
-
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
3229 |
-
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
3230 |
-
"dev": true,
|
3231 |
-
"optional": true,
|
3232 |
-
"requires": {
|
3233 |
-
"assert-plus": "1.0.0",
|
3234 |
-
"core-util-is": "1.0.2",
|
3235 |
-
"extsprintf": "1.3.0"
|
3236 |
-
}
|
3237 |
-
},
|
3238 |
-
"walkdir": {
|
3239 |
-
"version": "0.0.11",
|
3240 |
-
"resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz",
|
3241 |
-
"integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=",
|
3242 |
-
"dev": true
|
3243 |
-
},
|
3244 |
-
"which": {
|
3245 |
-
"version": "1.2.14",
|
3246 |
-
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
|
3247 |
-
"integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
|
3248 |
-
"dev": true,
|
3249 |
-
"requires": {
|
3250 |
-
"isexe": "2.0.0"
|
3251 |
-
}
|
3252 |
-
},
|
3253 |
-
"wide-align": {
|
3254 |
-
"version": "1.1.2",
|
3255 |
-
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
|
3256 |
-
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
|
3257 |
-
"dev": true,
|
3258 |
-
"requires": {
|
3259 |
-
"string-width": "1.0.2"
|
3260 |
-
}
|
3261 |
-
},
|
3262 |
-
"window-size": {
|
3263 |
-
"version": "0.1.0",
|
3264 |
-
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
|
3265 |
-
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
|
3266 |
-
"dev": true
|
3267 |
-
},
|
3268 |
-
"wordwrap": {
|
3269 |
-
"version": "0.0.2",
|
3270 |
-
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
3271 |
-
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
|
3272 |
-
"dev": true
|
3273 |
-
},
|
3274 |
-
"wrappy": {
|
3275 |
-
"version": "1.0.2",
|
3276 |
-
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
3277 |
-
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
3278 |
-
"dev": true
|
3279 |
-
},
|
3280 |
-
"xtend": {
|
3281 |
-
"version": "4.0.1",
|
3282 |
-
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
3283 |
-
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
3284 |
-
"dev": true
|
3285 |
-
},
|
3286 |
-
"yargs": {
|
3287 |
-
"version": "3.5.4",
|
3288 |
-
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz",
|
3289 |
-
"integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=",
|
3290 |
-
"dev": true,
|
3291 |
-
"requires": {
|
3292 |
-
"camelcase": "1.2.1",
|
3293 |
-
"decamelize": "1.2.0",
|
3294 |
-
"window-size": "0.1.0",
|
3295 |
-
"wordwrap": "0.0.2"
|
3296 |
-
},
|
3297 |
-
"dependencies": {
|
3298 |
-
"camelcase": {
|
3299 |
-
"version": "1.2.1",
|
3300 |
-
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
|
3301 |
-
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
|
3302 |
-
"dev": true
|
3303 |
-
}
|
3304 |
-
}
|
3305 |
-
},
|
3306 |
-
"zip-stream": {
|
3307 |
-
"version": "1.2.0",
|
3308 |
-
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz",
|
3309 |
-
"integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=",
|
3310 |
-
"dev": true,
|
3311 |
-
"requires": {
|
3312 |
-
"archiver-utils": "1.3.0",
|
3313 |
-
"compress-commons": "1.2.2",
|
3314 |
-
"lodash": "4.17.4",
|
3315 |
-
"readable-stream": "2.3.3"
|
3316 |
-
},
|
3317 |
-
"dependencies": {
|
3318 |
-
"lodash": {
|
3319 |
-
"version": "4.17.4",
|
3320 |
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
3321 |
-
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
3322 |
-
"dev": true
|
3323 |
-
}
|
3324 |
-
}
|
3325 |
-
},
|
3326 |
-
"zlib-browserify": {
|
3327 |
-
"version": "0.0.1",
|
3328 |
-
"resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz",
|
3329 |
-
"integrity": "sha1-T6akXQDbwV8xikr6HZr8Aljhdsw=",
|
3330 |
-
"dev": true
|
3331 |
-
}
|
3332 |
-
}
|
3333 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,301 +1,314 @@
|
|
1 |
-
=== WP Staging - DB & File Duplicator & Migration ===
|
2 |
-
|
3 |
-
Author URL: https://wordpress.org/plugins/wp-staging
|
4 |
-
Plugin URL: https://wordpress.org/plugins/wp-staging
|
5 |
-
Contributors: ReneHermi, WP-Staging
|
6 |
-
Donate link: https://wordpress.org/plugins/wp-staging
|
7 |
-
License: GPLv2 or later
|
8 |
-
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
-
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
-
Requires at least: 3.6+
|
11 |
-
Tested up to: 4.9
|
12 |
-
Stable tag: 2.1.
|
13 |
-
|
14 |
-
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
-
|
16 |
-
== Description ==
|
17 |
-
|
18 |
-
<strong>This cloning and staging plugin is well tested but work in progress. <br><br>
|
19 |
-
If you find any issue, please open a [support ticket](https://wp-staging.com/support/ "support ticket").
|
20 |
-
</strong>
|
21 |
-
<br /><br />
|
22 |
-
<strong>Note: </strong> For pushing plugins and theme files to live site, check out [https://wp-staging.com/](https://wp-staging.com/ "WP Staging Pro")
|
23 |
-
<br /><br />
|
24 |
-
<blockquote>
|
25 |
-
<h4> WP Staging for WordPress Migration </h4>
|
26 |
-
This duplicator plugin allows you to create an staging or development environment in seconds* <br /> <br />
|
27 |
-
It creates a clone of your website into a subfolder of your main WordPress installation including an entire copy of your database.
|
28 |
-
This sounds pretty simple and yes it is! All the hard time-consumptive database and file copying stuff including url replacements is done in the background.
|
29 |
-
<br /> <br />
|
30 |
-
I created this plugin because all other solutions are way too complex, overloaded with dozens of options or having server requirements which are not available on most shared hosting solutions.
|
31 |
-
All these reasons prevent user from testing new plugins and updates first before installing them on their live website, so its time to release a plugin which has the potential to be merged into everyone´s wordpress workflow.
|
32 |
-
<br /><br />
|
33 |
-
<p><small><em>* Time of creation depends on size of your database and file size</em></small></p>
|
34 |
-
</blockquote>
|
35 |
-
|
36 |
-
WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
* <strong>
|
45 |
-
<
|
46 |
-
<strong>
|
47 |
-
<br
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
<
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
There are
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
*
|
147 |
-
*
|
148 |
-
* Fix:
|
149 |
-
|
150 |
-
|
151 |
-
*
|
152 |
-
*
|
153 |
-
* Fix:
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
* Fix:
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
* New:
|
166 |
-
*
|
167 |
-
* New:
|
168 |
-
|
169 |
-
|
170 |
-
* Fix
|
171 |
-
* Fix:
|
172 |
-
|
173 |
-
= 2.1.
|
174 |
-
* Fix:
|
175 |
-
*
|
176 |
-
|
177 |
-
|
178 |
-
*
|
179 |
-
*
|
180 |
-
*
|
181 |
-
* Fix:
|
182 |
-
*
|
183 |
-
*
|
184 |
-
*
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
*
|
189 |
-
|
190 |
-
|
191 |
-
*
|
192 |
-
*
|
193 |
-
* Fix:
|
194 |
-
* Fix:
|
195 |
-
*
|
196 |
-
*
|
197 |
-
*
|
198 |
-
|
199 |
-
|
200 |
-
= 2.
|
201 |
-
*
|
202 |
-
|
203 |
-
= 2.0
|
204 |
-
*
|
205 |
-
|
206 |
-
|
207 |
-
* Fix:
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
*
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
* Fix:
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
*
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
*
|
236 |
-
|
237 |
-
= 1.1.
|
238 |
-
* Fix:
|
239 |
-
*
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
* New:
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
*
|
267 |
-
|
268 |
-
|
269 |
-
*
|
270 |
-
*
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
* Fix:
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
*
|
281 |
-
* Tweak:
|
282 |
-
|
283 |
-
|
284 |
-
*
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
* Fix:
|
289 |
-
* Fix:
|
290 |
-
*
|
291 |
-
|
292 |
-
|
293 |
-
*
|
294 |
-
*
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
=
|
301 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WP Staging - DB & File Duplicator & Migration ===
|
2 |
+
|
3 |
+
Author URL: https://wordpress.org/plugins/wp-staging
|
4 |
+
Plugin URL: https://wordpress.org/plugins/wp-staging
|
5 |
+
Contributors: ReneHermi, WP-Staging
|
6 |
+
Donate link: https://wordpress.org/plugins/wp-staging
|
7 |
+
License: GPLv2 or later
|
8 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
+
Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
|
10 |
+
Requires at least: 3.6+
|
11 |
+
Tested up to: 4.9
|
12 |
+
Stable tag: 2.1.9
|
13 |
+
|
14 |
+
A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
|
15 |
+
|
16 |
+
== Description ==
|
17 |
+
|
18 |
+
<strong>This cloning and staging plugin is well tested but work in progress. <br><br>
|
19 |
+
If you find any issue, please open a [support ticket](https://wp-staging.com/support/ "support ticket").
|
20 |
+
</strong>
|
21 |
+
<br /><br />
|
22 |
+
<strong>Note: </strong> For pushing & migrating plugins and theme files to live site, check out [https://wp-staging.com/](https://wp-staging.com/ "WP Staging Pro")
|
23 |
+
<br /><br />
|
24 |
+
<blockquote>
|
25 |
+
<h4> WP Staging for WordPress Migration </h4>
|
26 |
+
This duplicator plugin allows you to create an staging or development environment in seconds* <br /> <br />
|
27 |
+
It creates a clone of your website into a subfolder of your main WordPress installation including an entire copy of your database.
|
28 |
+
This sounds pretty simple and yes it is! All the hard time-consumptive database and file copying stuff including url replacements is done in the background.
|
29 |
+
<br /> <br />
|
30 |
+
I created this plugin because all other solutions are way too complex, overloaded with dozens of options or having server requirements which are not available on most shared hosting solutions.
|
31 |
+
All these reasons prevent user from testing new plugins and updates first before installing them on their live website, so its time to release a plugin which has the potential to be merged into everyone´s wordpress workflow.
|
32 |
+
<br /><br />
|
33 |
+
<p><small><em>* Time of creation depends on size of your database and file size</em></small></p>
|
34 |
+
</blockquote>
|
35 |
+
|
36 |
+
WP Staging helps you to prevent your website from being broken or unavailable because of installing untested plugin updates!
|
37 |
+
<p>Note: WordPress 5.0 will be shipped with a new visual editor called Gutenberg. Use WP Staging to check if Gutenberg editor is working as intended on your website and that all used plugins are compatible with that new editor.</p>
|
38 |
+
|
39 |
+
|
40 |
+
[youtube https://www.youtube.com/watch?v=Ye3fC6cdB3A]
|
41 |
+
|
42 |
+
= Main Features =
|
43 |
+
|
44 |
+
* <strong>Easy: </strong> Staging migration applicable for everyone. No configuration needed!
|
45 |
+
* <strong>Fast: </strong> Migration process lasts only a few seconds or minutes, depending on the site's size and server I/O power
|
46 |
+
* <strong>Safe: </strong> Access to staging site is granted for administrators only.
|
47 |
+
<br /><br />
|
48 |
+
<strong>More safe:</strong>
|
49 |
+
<br>
|
50 |
+
* Admin bar reflects that you are working on a staging site
|
51 |
+
* Extensive logging if duplication and migration process fails.
|
52 |
+
|
53 |
+
= What does not work or is not tested when running wordpress migration? =
|
54 |
+
|
55 |
+
* Wordpress migration of wordpress multisites (not tested)
|
56 |
+
* WordPress duplicating process on windows server (not tested but will probably work)
|
57 |
+
Edit: Duplication on windows server seems to be working well: [Read more](https://wordpress.org/support/topic/wont-copy-files?replies=5 "Read more")
|
58 |
+
|
59 |
+
|
60 |
+
<strong>Change your workflow of updating themes and plugins data:</strong>
|
61 |
+
|
62 |
+
1. Use WP Staging for migration of a production website to a clone site for staging purposes
|
63 |
+
2. Customize theme, configuration and plugins or install new plugins
|
64 |
+
3. Test everything on your staging site first
|
65 |
+
4. Everything running as expected? You are on the save side for migration of all these modifications to your production site!
|
66 |
+
|
67 |
+
|
68 |
+
<h3> Why should i use a staging website? </h3>
|
69 |
+
|
70 |
+
Plugin updates and theme customizations should be tested on a staging platform first. Its recommended to have the staging platform on the same server where the production website is located.
|
71 |
+
When you run a plugin update or plan to install a new one, it is a necessary task to check first the modifications on a clone of your production website.
|
72 |
+
This makes sure that any modifications is working on your website without throwing unexpected errors or preventing your site from loading. (Better known as the wordpress blank page error)
|
73 |
+
|
74 |
+
Testing a plugin update before installing it in live environment isn´t done very often by most user because existing staging solutions are too complex and need a lot of time to create a
|
75 |
+
up-to-date copy of your website.
|
76 |
+
|
77 |
+
Some people are also afraid of installing plugins updates because they follow the rule "never touch a running system" with having in mind that untested updates are increasing the risk of breaking their site.
|
78 |
+
I totally understand this and i am guilty as well here, but unfortunately this leads to one of the main reasons why WordPress installations are often outdated, not updated at all and unsecure due to this non-update behavior.
|
79 |
+
|
80 |
+
<strong> I think its time to change this, so i created "WP Staging" for WordPress migration of staging sites</strong>
|
81 |
+
|
82 |
+
<h3> Can´t i just use my local wordpress development copy for testing like xampp / lampp? </h3>
|
83 |
+
|
84 |
+
Nope! If your local hardware and software environment is not a 100% exact clone of your production server there is NO guarantee that every aspect
|
85 |
+
of your local copy is working on your live website exactely as you would expect it.
|
86 |
+
There are some obvious things like differences in the config of php and the server you are running but even such non obvious settings like the amount of ram or the
|
87 |
+
the cpu performance can lead to unexpected results on your production website.
|
88 |
+
There are dozens of other possible cause of failure which can not be handled well when you are testing your changes on a local staging platform.
|
89 |
+
|
90 |
+
This is were WP Staging steps in... Site cloning and staging site creation simplified!
|
91 |
+
|
92 |
+
<h3>I just want to migrate the database from one installation to another</h3>
|
93 |
+
If you want to migrate your local database to a already existing production site you can use a tool like WP Migrate DB.
|
94 |
+
WP Staging is only for creating a staging site with latest data from your production site. So it goes the opposite way of WP Migrate DB.
|
95 |
+
Both tools are excellent cooperating eachother.
|
96 |
+
|
97 |
+
<h3>What are the benefits compared to a plugin like Duplicator?</h3>
|
98 |
+
At first, i love the [Duplicator plugin](https://wordpress.org/plugins/duplicator/ "Duplicator plugin"). Duplicator is a great tool for migrating from development site to production one or from production site to development one.
|
99 |
+
The downside is that Duplicator needs adjustments, manually interventions and prerequirements for this. Duplicator also needs some skills to be able to create a development / staging site, where WP Staging does not need more than a click from you.
|
100 |
+
However, Duplicator is best placed to be a tool for first-time creation of your production site. This is something where it is very handy and powerful.
|
101 |
+
|
102 |
+
So, if you have created a local or webhosted development site and you need to migrate this site the first time to your production domain than you are doing nothing wrong with using
|
103 |
+
the Duplicator plugin! If you need all you latest production data like posts, updated plugins, theme data and styles in a testing environment than i recommend to use WP Staging instead!
|
104 |
+
|
105 |
+
= I need you feedback =
|
106 |
+
This plugin has been done in hundreds of hours to work on even the smallest shared webhosting package but i am limited in testing this only on a handful of different server so i need your help:
|
107 |
+
Please open a [support request](https://wordpress.org/support/plugin/wp-staging/ "support request") and describe your problem exactely. In wp-content/wp-staging/logs you find extended logfiles. Have a look at them and let me know the error-thrown lines.
|
108 |
+
|
109 |
+
|
110 |
+
= Important =
|
111 |
+
|
112 |
+
Per default the staging site will have permalinks disabled because the staging site will be cloned into a subfolder and regular permalinks are not working
|
113 |
+
without doing changes to your .htaccess or nginx.conf.
|
114 |
+
In the majority of cases this is abolutely fine for a staging platform and you still will be able to test new plugins and do some theme changes on your staging platform.
|
115 |
+
If you need the same permalink stucture on your staging platform as you have in your prodcution website you have to create a custom .htaccess for apache webserver
|
116 |
+
or to adjust your nginx.conf.
|
117 |
+
|
118 |
+
|
119 |
+
= How to install and setup? =
|
120 |
+
Install it via the admin dashboard and to 'Plugins', click 'Add New' and search the plugins for 'Staging'. Install the plugin with 'Install Now'.
|
121 |
+
After installation goto the settings page 'Staging' and do your adjustments there.
|
122 |
+
|
123 |
+
|
124 |
+
== Frequently Asked Questions ==
|
125 |
+
|
126 |
+
|
127 |
+
== Official Site ==
|
128 |
+
https://wp-staging.com
|
129 |
+
|
130 |
+
== Installation ==
|
131 |
+
1. Download the file "wp-staging" , unzip and place it in your wp-content/plugins/wp-staging folder. You can alternatively upload and install it via the WordPress plugin backend.
|
132 |
+
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
133 |
+
3. Start Plugins->Staging
|
134 |
+
|
135 |
+
== Screenshots ==
|
136 |
+
|
137 |
+
1. Step 1. Create new WordPress staging site
|
138 |
+
2. Step 2. Scanning your website for files and database tables
|
139 |
+
3. Step 3. Wordpress Staging site creation in progress
|
140 |
+
4. Finish!
|
141 |
+
|
142 |
+
== Changelog ==
|
143 |
+
|
144 |
+
= 2.1.9 =
|
145 |
+
* New: Performance improvement increase db query limit to 5000
|
146 |
+
* New: Detect automatically if WordPress is installed in sub folder
|
147 |
+
* Tweak: Tested up to WP 4.9.4
|
148 |
+
* Fix: Updating from an old version 1.1.6 < to latest version deletes the staging sites listing table
|
149 |
+
* Fix: Reduce memory size of the logging window to prevent browser timeouts
|
150 |
+
* Fix: Can not copy db table if table name contains the db prefix multiple times
|
151 |
+
* Fix: Some excluded folders are not ignored during copy process
|
152 |
+
* Fix: mod_security is causing script termination
|
153 |
+
* Fix: Skip directory listings for symlinks
|
154 |
+
|
155 |
+
= 2.1.8 =
|
156 |
+
* Fix: Increase the max memory consumption
|
157 |
+
|
158 |
+
= 2.1.7 =
|
159 |
+
* Tweak: Return more human readable error notices
|
160 |
+
* Fix: Cloning process stops due to file permission issue
|
161 |
+
* Fix: Exclude WP Super Cache from copying process because of bug in WP Super Cache, see https://github.com/Automattic/wp-super-cache/issues/505
|
162 |
+
|
163 |
+
= 2.1.6 =
|
164 |
+
* New: increased speed for cloning process by factor 5, using new method of file agregation
|
165 |
+
* New: Skip files larger than 8MB
|
166 |
+
* Fix: Additional checks to ensure that the root path is never deleted
|
167 |
+
* New: Compatible up to WP 4.9.1
|
168 |
+
|
169 |
+
= 2.1.5 =
|
170 |
+
* Fix. Change link to support
|
171 |
+
* Fix: Missing files in clone site if copy file limit is higher than 1
|
172 |
+
|
173 |
+
= 2.1.4 =
|
174 |
+
* Fix: Link to the staging site is missing a slash if WordPress is installed in subdir
|
175 |
+
* Tweak: Allow file copy limit 1 to prevent copy timeouts
|
176 |
+
|
177 |
+
= 2.1.3 =
|
178 |
+
* New: Add more details to tools->system info log for better debugging
|
179 |
+
* New: Add buttons to select all default wp tables with one click
|
180 |
+
* New: Show used db table in list of staging sites
|
181 |
+
* Fix: Delete staging site not possible if db prefix is same as one of the live site
|
182 |
+
* Fix: Edit/Update clone function is duplicating tables.
|
183 |
+
* Fix: Other staging site can be overwritten when Edit/Update clone function is executed
|
184 |
+
* Fix: Several improvements to improve reliability and prevent timeouts and fatal errors during cloning
|
185 |
+
|
186 |
+
= 2.1.2 =
|
187 |
+
* Fix: Remove LOCK_EX parameter in file_put_contents(). LOCK_EX is not working on several systems which results in cloning process timeouts
|
188 |
+
* Fix: Huge Performance improvement in copying process by removing duplicate file entries in the cache file. This also prevents weird timeout issues on some hosted websites
|
189 |
+
* Fix: Error 500 when debug mode is activated
|
190 |
+
* Fix: Limit maximum execution time to 30 seconds
|
191 |
+
* Fix: Sanitize Clone Names and Keys to fix "clone not found" issue in upgrade routine
|
192 |
+
* Fix: Do not clone the plugin wps-hide-login
|
193 |
+
* Fix: Staging sites can not be deleted if they are very big
|
194 |
+
* Fix: Link to staging site is undefined
|
195 |
+
* Tweak: Better admin message for asking for a review
|
196 |
+
* Tweak: Remove table wpstg_rmpermalinks_executed when plugin is uninstalled
|
197 |
+
* New: New setting to specify the maximum amount of files copied within one ajax call to fix godaddy and bluehost ajax 404 errors. Default 10 per batch
|
198 |
+
|
199 |
+
|
200 |
+
= 2.1.1 =
|
201 |
+
* New: Add link to tutorial explaining the process of pushing modification to the live site
|
202 |
+
|
203 |
+
= 2.1.0 =
|
204 |
+
* New: Exclude unneccessary files from cloning process: .tmp, .log, .htaccess, .git, .gitignore, desktop.ini, .DS_Store, .svn
|
205 |
+
* New: More details for debugging in Tools->System Info
|
206 |
+
* Fix: Check if tables in staging site exists before attempting to modify them
|
207 |
+
* Fix: WordPress in sub directories were not opening
|
208 |
+
* Fix: Nonce check not working if nonce life time is filtered by another plugin WP Bug: https://core.trac.wordpress.org/ticket/41617#comment:1
|
209 |
+
* Fix: Access to staging site not working, if WP_SITEURL and WP_HOME is defined in wp-config.php
|
210 |
+
* Tweak: Exclude wp-content/cache folder from copying process
|
211 |
+
|
212 |
+
|
213 |
+
= 2.0.9 =
|
214 |
+
* Skip Version
|
215 |
+
|
216 |
+
= 2.0.8 =
|
217 |
+
* Fix: After update from wpstg 1.6.x to 2.x previous settings were not imported resulting in cancelation of cloning process. Still not fixed in 2.0.7
|
218 |
+
|
219 |
+
= 2.0.7 =
|
220 |
+
* Fix: After update from wpstg 1.6.x to 2.x previous settings were not imported resulting in cancelation of cloning process
|
221 |
+
|
222 |
+
|
223 |
+
= 2.0.6 =
|
224 |
+
* Fix: Cancel Cloning button not working
|
225 |
+
* Fix: Limit max execution time to a maximum of 30sec to prevent high memory consumption and script timeouts
|
226 |
+
|
227 |
+
|
228 |
+
= 2.0.5 =
|
229 |
+
* New: Major version - Complete rewrite of the code base
|
230 |
+
* New: Batch processing allows to clone even huge sites without any timeouts
|
231 |
+
* New: Preparation for WP QUADS PRO with ability to copy file changes back to live site
|
232 |
+
* New: Bypass (broken) third party plugins during wp staging related ajax requests to prevent processing errors. Use a mu plugin for this.
|
233 |
+
|
234 |
+
= 1.1.6 =
|
235 |
+
* New: Add download link to WP Staging Beta Version 2.0.1
|
236 |
+
|
237 |
+
= 1.1.5 =
|
238 |
+
* Fix: Admin notice is throwing a false positive write permission error
|
239 |
+
* New: Move log folder to wp-content/uploads/wp-staging/logs
|
240 |
+
* New: Tested up to WP 4.7.3
|
241 |
+
|
242 |
+
= 1.1.4 =
|
243 |
+
* Fix: Fatal error Unsupported operand types
|
244 |
+
|
245 |
+
= 1.1.3 =
|
246 |
+
* New: Tested up to wp 4.7.2
|
247 |
+
* Fix: Arrows in drop down for folder selection are distorted
|
248 |
+
* Tweak: Show working log as default to make debugging easier
|
249 |
+
|
250 |
+
= 1.1.2 =
|
251 |
+
* Fix: Settings are not deleted when plugin is removed
|
252 |
+
* Fix: Staging site is available for non administrators
|
253 |
+
|
254 |
+
= 1.1.1 =
|
255 |
+
* Fix: Change rating url
|
256 |
+
|
257 |
+
= 1.1.0 =
|
258 |
+
* New: Tested up to WP 4.6
|
259 |
+
* New: Create a poll and ask what feature is most required
|
260 |
+
|
261 |
+
= 1.0.9 =
|
262 |
+
* Fix: Undefined WPSTG() warning
|
263 |
+
* Fix: Change compatibility version to wp 4.5.3
|
264 |
+
|
265 |
+
= 1.0.8 =
|
266 |
+
* Tested up to WP 4.5.2
|
267 |
+
|
268 |
+
= 1.0.7 =
|
269 |
+
* Fix: Activation hook is not fired and staging site is not working properly
|
270 |
+
* Performance: Increase default query copy limit to 1000
|
271 |
+
|
272 |
+
= 1.0.6 =
|
273 |
+
* Fix: Uninstalling plugin throwing error
|
274 |
+
* Fix: Error permission admin notice although permission issues are correct
|
275 |
+
|
276 |
+
|
277 |
+
= 1.0.5 =
|
278 |
+
* New: Tested up to WP 4.5
|
279 |
+
* Fix: Download system log not working
|
280 |
+
* Fix: Click on Optimizer "Select all | none | invert" links leads to jumping
|
281 |
+
* Tweak: Make clear that unselecting a checkbox will exlude table or file from copy process
|
282 |
+
* Tweak: Remove unnecessary text
|
283 |
+
* Tweak: Change beta notice in dashboard. WP Staging is stable
|
284 |
+
* Tweak: Change twitter handle to @wpstg
|
285 |
+
|
286 |
+
= 1.0.3 =
|
287 |
+
* Fix: Missing const MASHFS_VERSION
|
288 |
+
* Fix: Remove error "table XY has been created, BUT inserting rows failed."
|
289 |
+
* Fix: Not tested up to 4.4.2 message shown although it's tested up to WP 4.4.2
|
290 |
+
* New: Disable either free or pro version and does not allow to have both version enabled at the same time
|
291 |
+
|
292 |
+
= 1.0.2 =
|
293 |
+
* Tweak: Change setting description of uninstall option
|
294 |
+
* Tweak: Lower tags in readme.txt
|
295 |
+
|
296 |
+
= 1.0.1 =
|
297 |
+
* New: Orange colored admin bar on staging site for better visualization and comparision between production live site and staging site
|
298 |
+
* Tweak: Remove contact link on multisite notification
|
299 |
+
|
300 |
+
= 1.0.0 =
|
301 |
+
* Fix: Do not follow symlinks during file copy process
|
302 |
+
* Fix: css error
|
303 |
+
* Fix: Show "not-compatible" notice only when blog version is higher than plugin tested version.
|
304 |
+
* Fix: undefined var $size
|
305 |
+
* Fix: Check if $path is null before writing to remaining_files.json
|
306 |
+
* Fix: $db_helper undefined message
|
307 |
+
* Fix: Skip non utf8 encoded files during copying process
|
308 |
+
|
309 |
+
Complete changelog: [https://wp-staging.com/changelog.txt](https://wp-staging.com/changelog.txt)
|
310 |
+
|
311 |
+
== Upgrade Notice ==
|
312 |
+
|
313 |
+
= 2.1.7 =
|
314 |
+
2.1.7 * Update for WordPress 4.9.1. Preparations for Database Migration
|
uninstall.php
CHANGED
@@ -1,89 +1,89 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPStaging\Backend;
|
4 |
-
|
5 |
-
use WPStaging\Backend\Optimizer\Optimizer;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Uninstall WP-Staging
|
9 |
-
*
|
10 |
-
* @package WPSTG
|
11 |
-
* @subpackage Uninstall
|
12 |
-
* @copyright Copyright (c) 2015, René Hermenau
|
13 |
-
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
14 |
-
* @since 0.9.0
|
15 |
-
*/
|
16 |
-
// No direct access
|
17 |
-
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
18 |
-
exit;
|
19 |
-
}
|
20 |
-
|
21 |
-
class uninstall {
|
22 |
-
|
23 |
-
public function __construct() {
|
24 |
-
|
25 |
-
// Plugin Folder Path
|
26 |
-
if (!defined('WPSTG_PLUGIN_DIR')) {
|
27 |
-
define('WPSTG_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Path to main WP Staging class
|
32 |
-
* Make sure to not redeclare class in case free version has been installed previosly
|
33 |
-
*/
|
34 |
-
if (!class_exists('WPStaging\WPStaging')) {
|
35 |
-
require_once plugin_dir_path(__FILE__) . "apps/Core/WPStaging.php";
|
36 |
-
}
|
37 |
-
$wpStaging = \WPStaging\WPStaging::getInstance();
|
38 |
-
|
39 |
-
// Delete our must use plugin
|
40 |
-
$this->deleteMuPlugin();
|
41 |
-
|
42 |
-
$this->init();
|
43 |
-
}
|
44 |
-
|
45 |
-
private function init() {
|
46 |
-
|
47 |
-
$options = json_decode(json_encode(get_option("wpstg_settings", array())));
|
48 |
-
|
49 |
-
if (isset($options->unInstallOnDelete) && '1' === $options->unInstallOnDelete) {
|
50 |
-
// Delete options
|
51 |
-
delete_option("wpstg_version_upgraded_from");
|
52 |
-
delete_option("wpstg_version");
|
53 |
-
delete_option("wpstg_installDate");
|
54 |
-
delete_option("wpstg_firsttime");
|
55 |
-
delete_option("wpstg_is_staging_site");
|
56 |
-
delete_option("wpstg_settings");
|
57 |
-
delete_option("wpstg_rmpermalinks_executed");
|
58 |
-
|
59 |
-
/* Do not delete these fields without actually deleting the staging site
|
60 |
-
* @create a delete routine which deletes the staging sites first
|
61 |
-
*/
|
62 |
-
//delete_option( "wpstg_existing_clones" );
|
63 |
-
//delete_option( "wpstg_existing_clones_beta" );
|
64 |
-
// Old wpstg 1.3 options for admin notices
|
65 |
-
delete_option("wpstg_start_poll");
|
66 |
-
delete_option("wpstg_hide_beta");
|
67 |
-
delete_option("wpstg_RatingDiv");
|
68 |
-
|
69 |
-
// New 2.x options for admin notices
|
70 |
-
delete_option("wpstg_poll");
|
71 |
-
delete_option("wpstg_rating");
|
72 |
-
delete_option("wpstg_beta");
|
73 |
-
|
74 |
-
// Delete events
|
75 |
-
wp_clear_scheduled_hook('wpstg_weekly_event');
|
76 |
-
}
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* delete MuPlugin
|
81 |
-
*/
|
82 |
-
private function deleteMuPlugin() {
|
83 |
-
$optimizer = new Optimizer;
|
84 |
-
$optimizer->unstallOptimizer();
|
85 |
-
}
|
86 |
-
|
87 |
-
}
|
88 |
-
|
89 |
-
new uninstall();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPStaging\Backend;
|
4 |
+
|
5 |
+
use WPStaging\Backend\Optimizer\Optimizer;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Uninstall WP-Staging
|
9 |
+
*
|
10 |
+
* @package WPSTG
|
11 |
+
* @subpackage Uninstall
|
12 |
+
* @copyright Copyright (c) 2015, René Hermenau
|
13 |
+
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
14 |
+
* @since 0.9.0
|
15 |
+
*/
|
16 |
+
// No direct access
|
17 |
+
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
18 |
+
exit;
|
19 |
+
}
|
20 |
+
|
21 |
+
class uninstall {
|
22 |
+
|
23 |
+
public function __construct() {
|
24 |
+
|
25 |
+
// Plugin Folder Path
|
26 |
+
if (!defined('WPSTG_PLUGIN_DIR')) {
|
27 |
+
define('WPSTG_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Path to main WP Staging class
|
32 |
+
* Make sure to not redeclare class in case free version has been installed previosly
|
33 |
+
*/
|
34 |
+
if (!class_exists('WPStaging\WPStaging')) {
|
35 |
+
require_once plugin_dir_path(__FILE__) . "apps/Core/WPStaging.php";
|
36 |
+
}
|
37 |
+
$wpStaging = \WPStaging\WPStaging::getInstance();
|
38 |
+
|
39 |
+
// Delete our must use plugin
|
40 |
+
$this->deleteMuPlugin();
|
41 |
+
|
42 |
+
$this->init();
|
43 |
+
}
|
44 |
+
|
45 |
+
private function init() {
|
46 |
+
|
47 |
+
$options = json_decode(json_encode(get_option("wpstg_settings", array())));
|
48 |
+
|
49 |
+
if (isset($options->unInstallOnDelete) && '1' === $options->unInstallOnDelete) {
|
50 |
+
// Delete options
|
51 |
+
delete_option("wpstg_version_upgraded_from");
|
52 |
+
delete_option("wpstg_version");
|
53 |
+
delete_option("wpstg_installDate");
|
54 |
+
delete_option("wpstg_firsttime");
|
55 |
+
delete_option("wpstg_is_staging_site");
|
56 |
+
delete_option("wpstg_settings");
|
57 |
+
delete_option("wpstg_rmpermalinks_executed");
|
58 |
+
|
59 |
+
/* Do not delete these fields without actually deleting the staging site
|
60 |
+
* @create a delete routine which deletes the staging sites first
|
61 |
+
*/
|
62 |
+
//delete_option( "wpstg_existing_clones" );
|
63 |
+
//delete_option( "wpstg_existing_clones_beta" );
|
64 |
+
// Old wpstg 1.3 options for admin notices
|
65 |
+
delete_option("wpstg_start_poll");
|
66 |
+
delete_option("wpstg_hide_beta");
|
67 |
+
delete_option("wpstg_RatingDiv");
|
68 |
+
|
69 |
+
// New 2.x options for admin notices
|
70 |
+
delete_option("wpstg_poll");
|
71 |
+
delete_option("wpstg_rating");
|
72 |
+
delete_option("wpstg_beta");
|
73 |
+
|
74 |
+
// Delete events
|
75 |
+
wp_clear_scheduled_hook('wpstg_weekly_event');
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* delete MuPlugin
|
81 |
+
*/
|
82 |
+
private function deleteMuPlugin() {
|
83 |
+
$optimizer = new Optimizer;
|
84 |
+
$optimizer->unstallOptimizer();
|
85 |
+
}
|
86 |
+
|
87 |
+
}
|
88 |
+
|
89 |
+
new uninstall();
|
wp-staging.php
CHANGED
@@ -1,91 +1,91 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Plugin Name: WP Staging
|
5 |
-
* Plugin URI: https://wordpress.org/plugins/wp-staging
|
6 |
-
* Description: Create a staging clone site for testing & developing
|
7 |
-
* Author: WP-Staging
|
8 |
-
* Author URI: https://wp-staging.com
|
9 |
-
* Contributors: ReneHermi, ilgityildirim
|
10 |
-
* Version: 2.1.
|
11 |
-
* Text Domain: wpstg
|
12 |
-
* Domain Path: /languages/
|
13 |
-
|
14 |
-
*
|
15 |
-
* WP-Staging is free software: you can redistribute it and/or modify
|
16 |
-
* it under the terms of the GNU General Public License as published by
|
17 |
-
* the Free Software Foundation, either version 2 of the License, or
|
18 |
-
* any later version.
|
19 |
-
*
|
20 |
-
* WP-Staging is distributed in the hope that it will be useful,
|
21 |
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22 |
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
23 |
-
* GNU General Public License for more details.
|
24 |
-
*
|
25 |
-
* You should have received a copy of the GNU General Public License
|
26 |
-
* along with Staging. If not, see <http://www.gnu.org/licenses/>.
|
27 |
-
*
|
28 |
-
* @package WPSTG
|
29 |
-
* @category Core
|
30 |
-
* @author René Hermenau, Ilgıt Yıldırım
|
31 |
-
*/
|
32 |
-
|
33 |
-
// No Direct Access
|
34 |
-
if (!defined("WPINC"))
|
35 |
-
{
|
36 |
-
die;
|
37 |
-
}
|
38 |
-
|
39 |
-
// Plugin Folder Path
|
40 |
-
if( !defined( 'WPSTG_PLUGIN_DIR' ) ) {
|
41 |
-
define( 'WPSTG_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
42 |
-
}
|
43 |
-
// Plugin Folder URL
|
44 |
-
if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
|
45 |
-
define( 'WPSTG_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
46 |
-
}
|
47 |
-
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Fix nonce check
|
51 |
-
* https://core.trac.wordpress.org/ticket/41617#ticket
|
52 |
-
* @param int $seconds
|
53 |
-
* @return int
|
54 |
-
*/
|
55 |
-
function wpstg_overwrite_nonce($seconds){
|
56 |
-
return 86400;
|
57 |
-
}
|
58 |
-
add_filter('nonce_life', 'wpstg_overwrite_nonce', 99999);
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Path to main WP Staging class
|
62 |
-
* Make sure to not redeclare class in case free version has been installed previosly
|
63 |
-
*/
|
64 |
-
if (!class_exists( 'WPStaging\WPStaging' )){
|
65 |
-
require_once plugin_dir_path(__FILE__) . "apps/Core/WPStaging.php";
|
66 |
-
}
|
67 |
-
|
68 |
-
$wpStaging = \WPStaging\WPStaging::getInstance();
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Load a few important WP globals into WPStaging class to make them available via dependancy injection
|
72 |
-
*/
|
73 |
-
|
74 |
-
// Wordpress DB Object
|
75 |
-
if (isset($wpdb))
|
76 |
-
{
|
77 |
-
$wpStaging->set("wpdb", $wpdb);
|
78 |
-
}
|
79 |
-
|
80 |
-
// WordPress Filter Object
|
81 |
-
if (isset($wp_filter))
|
82 |
-
{
|
83 |
-
$wpStaging->set("wp_filter", function() use(&$wp_filter) {
|
84 |
-
return $wp_filter;
|
85 |
-
});
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Inititalize WPStaging
|
90 |
-
*/
|
91 |
-
$wpStaging->run();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Plugin Name: WP Staging
|
5 |
+
* Plugin URI: https://wordpress.org/plugins/wp-staging
|
6 |
+
* Description: Create a staging clone site for testing & developing
|
7 |
+
* Author: WP-Staging
|
8 |
+
* Author URI: https://wp-staging.com
|
9 |
+
* Contributors: ReneHermi, ilgityildirim
|
10 |
+
* Version: 2.1.9
|
11 |
+
* Text Domain: wpstg
|
12 |
+
* Domain Path: /languages/
|
13 |
+
|
14 |
+
*
|
15 |
+
* WP-Staging is free software: you can redistribute it and/or modify
|
16 |
+
* it under the terms of the GNU General Public License as published by
|
17 |
+
* the Free Software Foundation, either version 2 of the License, or
|
18 |
+
* any later version.
|
19 |
+
*
|
20 |
+
* WP-Staging is distributed in the hope that it will be useful,
|
21 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
23 |
+
* GNU General Public License for more details.
|
24 |
+
*
|
25 |
+
* You should have received a copy of the GNU General Public License
|
26 |
+
* along with Staging. If not, see <http://www.gnu.org/licenses/>.
|
27 |
+
*
|
28 |
+
* @package WPSTG
|
29 |
+
* @category Core
|
30 |
+
* @author René Hermenau, Ilgıt Yıldırım
|
31 |
+
*/
|
32 |
+
|
33 |
+
// No Direct Access
|
34 |
+
if (!defined("WPINC"))
|
35 |
+
{
|
36 |
+
die;
|
37 |
+
}
|
38 |
+
|
39 |
+
// Plugin Folder Path
|
40 |
+
if( !defined( 'WPSTG_PLUGIN_DIR' ) ) {
|
41 |
+
define( 'WPSTG_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
42 |
+
}
|
43 |
+
// Plugin Folder URL
|
44 |
+
if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
|
45 |
+
define( 'WPSTG_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Fix nonce check
|
51 |
+
* https://core.trac.wordpress.org/ticket/41617#ticket
|
52 |
+
* @param int $seconds
|
53 |
+
* @return int
|
54 |
+
*/
|
55 |
+
function wpstg_overwrite_nonce($seconds){
|
56 |
+
return 86400;
|
57 |
+
}
|
58 |
+
add_filter('nonce_life', 'wpstg_overwrite_nonce', 99999);
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Path to main WP Staging class
|
62 |
+
* Make sure to not redeclare class in case free version has been installed previosly
|
63 |
+
*/
|
64 |
+
if (!class_exists( 'WPStaging\WPStaging' )){
|
65 |
+
require_once plugin_dir_path(__FILE__) . "apps/Core/WPStaging.php";
|
66 |
+
}
|
67 |
+
|
68 |
+
$wpStaging = \WPStaging\WPStaging::getInstance();
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Load a few important WP globals into WPStaging class to make them available via dependancy injection
|
72 |
+
*/
|
73 |
+
|
74 |
+
// Wordpress DB Object
|
75 |
+
if (isset($wpdb))
|
76 |
+
{
|
77 |
+
$wpStaging->set("wpdb", $wpdb);
|
78 |
+
}
|
79 |
+
|
80 |
+
// WordPress Filter Object
|
81 |
+
if (isset($wp_filter))
|
82 |
+
{
|
83 |
+
$wpStaging->set("wp_filter", function() use(&$wp_filter) {
|
84 |
+
return $wp_filter;
|
85 |
+
});
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Inititalize WPStaging
|
90 |
+
*/
|
91 |
+
$wpStaging->run();
|