Version Description
- New: Incremental backup capability for ManageWP Orion.
Download this release
Release Info
Developer | freediver |
Plugin | ManageWP Worker |
Version | 4.1.0 |
Comparing to | |
See all releases |
Code changes from version 4.0.1 to 4.1.0
- functions.php +27 -7
- init.php +28 -14
- publickeys/{managewp_mt.pub → ManageWP_mt.pub} +0 -0
- readme.txt +80 -18
- src/Google/IO/Stream.php +5 -0
- src/MMB/Backup.php +53 -16
- src/MMB/Core.php +4 -30
- src/MMB/Helper.php +3 -115
- src/MMB/Installer.php +21 -17
- src/MMB/Stats.php +13 -20
- src/MWP/Action/DestroySessions.php +21 -0
- src/MWP/Action/GetState.php +29 -5
- src/MWP/Action/IncrementalBackup/Abstract.php +75 -0
- src/MWP/Action/IncrementalBackup/ChecksumTables.php +28 -0
- src/MWP/Action/IncrementalBackup/DumpTables.php +113 -0
- src/MWP/Action/IncrementalBackup/FetchFiles.php +45 -0
- src/MWP/Action/IncrementalBackup/HashFiles.php +77 -0
- src/MWP/Action/IncrementalBackup/ListFiles.php +220 -0
- src/MWP/Action/IncrementalBackup/ListTables.php +22 -0
- src/MWP/Action/IncrementalBackup/Stats.php +72 -0
- src/MWP/Action/IncrementalBackup/UploadCloner.php +35 -0
- src/MWP/Backup/ArrayHelper.php +15 -0
- src/MWP/Backup/MysqlDump/QuerySequenceDump.php +5 -4
- src/MWP/Event/ActionRequest.php +12 -1
- src/MWP/EventListener/ActionException/MultipartException.php +52 -0
- src/MWP/EventListener/ActionRequest/LogRequest.php +37 -0
- src/MWP/EventListener/{MasterRequest → ActionRequest}/SetCurrentUser.php +20 -16
- src/MWP/EventListener/ActionRequest/SetSettings.php +86 -2
- src/MWP/EventListener/ActionResponse/FetchFiles.php +71 -0
- src/MWP/EventListener/ActionResponse/SetLegacyPhpExecutionData.php +1 -3
- src/MWP/EventListener/ActionResponse/SetLegacyWebsiteConnectionData.php +9 -5
- src/MWP/EventListener/ActionResponse/SetUpdaterLog.php +46 -0
- src/MWP/EventListener/FixCompatibility.php +34 -0
- src/MWP/EventListener/MasterRequest/SetRequestSettings.php +77 -0
- src/MWP/EventListener/MasterResponse/LogResponse.php +48 -0
- src/MWP/EventListener/PublicRequest/AddStatusPage.php +73 -0
- src/MWP/EventListener/PublicRequest/AutomaticLogin.php +32 -1
- src/MWP/EventListener/PublicRequest/BrandContactSupport.php +26 -23
- src/MWP/EventListener/PublicRequest/SetHitCounter.php +15 -3
- src/MWP/EventListener/PublicRequest/SetPluginInfo.php +26 -2
- src/MWP/Http/JsonResponse.php +2 -2
- src/MWP/Http/MultipartResponse.php +129 -0
- src/MWP/Http/MultipartResponsePart.php +86 -0
- src/MWP/Http/RedirectResponse.php +2 -2
- src/MWP/Http/Response.php +107 -5
- src/MWP/Http/StreamingResponseInterface.php +17 -0
- src/MWP/IncrementalBackup/Database/Configuration.php +207 -0
- src/MWP/IncrementalBackup/Database/ConnectionInterface.php +26 -0
- src/MWP/IncrementalBackup/Database/DumpOptions.php +87 -0
- src/MWP/IncrementalBackup/Database/DumperInterface.php +19 -0
- src/MWP/IncrementalBackup/Database/Exception.php +13 -0
- src/MWP/IncrementalBackup/Database/Exception/ConnectionException.php +13 -0
- src/MWP/IncrementalBackup/Database/MysqlConnection.php +77 -0
- src/MWP/IncrementalBackup/Database/MysqlDumpDumper.php +88 -0
- src/MWP/IncrementalBackup/Database/MysqlStatement.php +50 -0
- src/MWP/IncrementalBackup/Database/MysqliConnection.php +70 -0
- src/MWP/IncrementalBackup/Database/MysqliStatement.php +52 -0
- src/MWP/IncrementalBackup/Database/PdoConnection.php +87 -0
- src/MWP/IncrementalBackup/Database/PdoStatement.php +39 -0
- src/MWP/IncrementalBackup/Database/PhpDumper.php +61 -0
- src/MWP/IncrementalBackup/Database/StatementInterface.php +22 -0
- src/MWP/IncrementalBackup/Database/StreamableQuerySequenceDump.php +249 -0
- src/MWP/IncrementalBackup/FileReader.php +79 -0
- src/MWP/IncrementalBackup/HashComputer.php +131 -0
- src/MWP/IncrementalBackup/Model/FetchFilesResult.php +67 -0
- src/MWP/IncrementalBackup/Model/File.php +55 -0
- src/MWP/IncrementalBackup/Model/ServerStatistics.php +117 -0
- src/MWP/ServiceContainer/Abstract.php +56 -0
- src/MWP/ServiceContainer/Interface.php +15 -0
- src/MWP/ServiceContainer/Production.php +74 -26
- src/MWP/Signer/PhpSecLibSigner.php +4 -2
- src/MWP/Stream/Append.php +131 -0
- src/MWP/Stream/Buffer.php +96 -0
- src/MWP/Stream/Callable.php +116 -0
- src/MWP/Stream/Interface.php +55 -0
- src/MWP/Stream/LazyFile.php +130 -0
- src/MWP/Stream/Limit.php +153 -0
- src/MWP/Stream/ProcessOutput.php +49 -0
- src/MWP/Stream/Stream.php +132 -0
- src/MWP/System/Environment.php +55 -0
- src/MWP/System/Utils.php +49 -0
- src/MWP/Updater/TraceableUpdaterSkin.php +183 -0
- src/MWP/WordPress/Context.php +77 -4
- src/MWP/WordPress/SessionStore.php +86 -0
- src/MWP/Worker/Exception.php +9 -3
- src/MWP/Worker/Kernel.php +1 -1
- src/MWP/Worker/Request.php +1 -1
- src/Monolog/Formatter/LineFormatter.php +1 -1
- version +2 -2
functions.php
CHANGED
@@ -379,6 +379,10 @@ function mwp_is_nio_shell_available()
|
|
379 |
|
380 |
function mwp_is_shell_available()
|
381 |
{
|
|
|
|
|
|
|
|
|
382 |
if (mwp_is_safe_mode()) {
|
383 |
return false;
|
384 |
}
|
@@ -512,12 +516,6 @@ function mmb_parse_request()
|
|
512 |
|
513 |
function mmb_response($response = false, $success = true)
|
514 |
{
|
515 |
-
mwp_logger()->debug('Master response: {action_response_status}', array(
|
516 |
-
'action_response_status' => $success ? 'success' : 'error',
|
517 |
-
'action_response' => $response,
|
518 |
-
'headers_sent' => headers_sent(),
|
519 |
-
));
|
520 |
-
|
521 |
if (!$success) {
|
522 |
if (!is_scalar($response)) {
|
523 |
$response = json_encode($response);
|
@@ -571,7 +569,7 @@ function mmb_stats_get($params)
|
|
571 |
mwp_context()->requirePostTypes();
|
572 |
mwp_context()->requireTheme();
|
573 |
|
574 |
-
$data = array_merge($mmb_core->stats_instance->get($params)
|
575 |
mmb_response($data, true);
|
576 |
}
|
577 |
|
@@ -1480,3 +1478,25 @@ function mmb_change_comment_status($params)
|
|
1480 |
mmb_response('Comment not updated', false);
|
1481 |
}
|
1482 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
|
380 |
function mwp_is_shell_available()
|
381 |
{
|
382 |
+
if (mwp_container()->getParameter('disable_shell')) {
|
383 |
+
return false;
|
384 |
+
}
|
385 |
+
|
386 |
if (mwp_is_safe_mode()) {
|
387 |
return false;
|
388 |
}
|
516 |
|
517 |
function mmb_response($response = false, $success = true)
|
518 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
519 |
if (!$success) {
|
520 |
if (!is_scalar($response)) {
|
521 |
$response = json_encode($response);
|
569 |
mwp_context()->requirePostTypes();
|
570 |
mwp_context()->requireTheme();
|
571 |
|
572 |
+
$data = array_merge(mmb_pre_init_stats($params), $mmb_core->stats_instance->get($params));
|
573 |
mmb_response($data, true);
|
574 |
}
|
575 |
|
1478 |
mmb_response('Comment not updated', false);
|
1479 |
}
|
1480 |
}
|
1481 |
+
|
1482 |
+
function mwp_uninstall()
|
1483 |
+
{
|
1484 |
+
$loaderName = '0-worker.php';
|
1485 |
+
try {
|
1486 |
+
$mustUsePluginDir = rtrim(WPMU_PLUGIN_DIR, '/');
|
1487 |
+
$loaderPath = $mustUsePluginDir.'/'.$loaderName;
|
1488 |
+
|
1489 |
+
if (!file_exists($loaderPath)) {
|
1490 |
+
return;
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
$removed = @unlink($loaderPath);
|
1494 |
+
|
1495 |
+
if (!$removed) {
|
1496 |
+
$error = error_get_last();
|
1497 |
+
throw new Exception(sprintf('Unable to remove loader: %s', $error['message']));
|
1498 |
+
}
|
1499 |
+
} catch (Exception $e) {
|
1500 |
+
mwp_logger()->error('Unable to remove loader', array('exception' => $e));
|
1501 |
+
}
|
1502 |
+
}
|
init.php
CHANGED
@@ -3,18 +3,21 @@
|
|
3 |
Plugin Name: ManageWP - Worker
|
4 |
Plugin URI: https://managewp.com
|
5 |
Description: ManageWP Worker plugin allows you to manage your WordPress sites from one dashboard. Visit <a href="https://managewp.com">ManageWP.com</a> for more information.
|
6 |
-
Version: 4.0
|
7 |
Author: ManageWP
|
8 |
Author URI: https://managewp.com
|
9 |
License: GPL2
|
10 |
*/
|
11 |
|
12 |
-
|
13 |
-
*
|
14 |
-
*
|
15 |
-
*
|
16 |
-
*
|
17 |
-
|
|
|
|
|
|
|
18 |
if (!defined('ABSPATH')) {
|
19 |
exit;
|
20 |
}
|
@@ -86,8 +89,8 @@ if (!function_exists('mwp_fail_safe')):
|
|
86 |
if (!empty($workerSettings['dataown'])) {
|
87 |
$userID = (int) $workerSettings['dataown'];
|
88 |
}
|
89 |
-
$body = sprintf(
|
90 |
-
$mailFn('
|
91 |
|
92 |
// If we're inside a cron scope, don't attempt to hide this error.
|
93 |
if (defined('DOING_CRON') && DOING_CRON) {
|
@@ -120,6 +123,8 @@ if (!class_exists('MwpWorkerResponder', false)):
|
|
120 |
|
121 |
private $container;
|
122 |
|
|
|
|
|
123 |
function __construct(MWP_ServiceContainer_Interface $container)
|
124 |
{
|
125 |
$this->container = $container;
|
@@ -133,7 +138,16 @@ if (!class_exists('MwpWorkerResponder', false)):
|
|
133 |
$lastResponse = $responseEvent->getResponse();
|
134 |
|
135 |
if ($lastResponse !== null) {
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
exit;
|
138 |
}
|
139 |
} elseif ($e !== null) {
|
@@ -191,11 +205,11 @@ if (!function_exists('mwp_init')):
|
|
191 |
spl_autoload_register('mwp_autoload', true, true);
|
192 |
}
|
193 |
|
194 |
-
$GLOBALS['MMB_WORKER_VERSION'] = '4.0
|
195 |
-
$GLOBALS['MMB_WORKER_REVISION'] = '2015-
|
196 |
$GLOBALS['mmb_plugin_dir'] = WP_PLUGIN_DIR.'/'.basename(dirname(__FILE__));
|
197 |
$GLOBALS['_mmb_item_filter'] = array();
|
198 |
-
$GLOBALS['mmb_core'] = $core = $mmb_core_backup = new MMB_Core();
|
199 |
|
200 |
$siteUrl = function_exists('get_site_option') ? get_site_option('siteurl') : get_option('siteurl');
|
201 |
define('MMB_XFRAME_COOKIE', 'wordpress_'.md5($siteUrl).'_xframe');
|
@@ -223,7 +237,7 @@ if (!function_exists('mwp_init')):
|
|
223 |
// Plugin management hooks.
|
224 |
register_activation_hook(__FILE__, array($core, 'install'));
|
225 |
register_deactivation_hook(__FILE__, array($core, 'deactivate'));
|
226 |
-
register_uninstall_hook(__FILE__,
|
227 |
|
228 |
// Don't send the "X-Frame-Options: SAMEORIGIN" header if we're logging in inside an iframe.
|
229 |
if (isset($_COOKIE[MMB_XFRAME_COOKIE])) {
|
3 |
Plugin Name: ManageWP - Worker
|
4 |
Plugin URI: https://managewp.com
|
5 |
Description: ManageWP Worker plugin allows you to manage your WordPress sites from one dashboard. Visit <a href="https://managewp.com">ManageWP.com</a> for more information.
|
6 |
+
Version: 4.1.0
|
7 |
Author: ManageWP
|
8 |
Author URI: https://managewp.com
|
9 |
License: GPL2
|
10 |
*/
|
11 |
|
12 |
+
/*
|
13 |
+
* This file is part of the ManageWP Worker plugin.
|
14 |
+
*
|
15 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
16 |
+
*
|
17 |
+
* For the full copyright and license information, please view the LICENSE
|
18 |
+
* file that was distributed with this source code.
|
19 |
+
*/
|
20 |
+
|
21 |
if (!defined('ABSPATH')) {
|
22 |
exit;
|
23 |
}
|
89 |
if (!empty($workerSettings['dataown'])) {
|
90 |
$userID = (int) $workerSettings['dataown'];
|
91 |
}
|
92 |
+
$body = sprintf("Worker deactivation due to an error. The site that was affected - %s. User email - %s (User ID: %s). Worker version: %s (%s). The error that caused this:\n<pre>%s</pre>", $siteUrl, $to, $userID, $GLOBALS['MMB_WORKER_VERSION'], $GLOBALS['MMB_WORKER_REVISION'], $fullError);
|
93 |
+
$mailFn('dev@managewp.com', $title, $body);
|
94 |
|
95 |
// If we're inside a cron scope, don't attempt to hide this error.
|
96 |
if (defined('DOING_CRON') && DOING_CRON) {
|
123 |
|
124 |
private $container;
|
125 |
|
126 |
+
private $responseSent = false;
|
127 |
+
|
128 |
function __construct(MWP_ServiceContainer_Interface $container)
|
129 |
{
|
130 |
$this->container = $container;
|
138 |
$lastResponse = $responseEvent->getResponse();
|
139 |
|
140 |
if ($lastResponse !== null) {
|
141 |
+
if (!$this->responseSent) {
|
142 |
+
// This looks pretty ugly, but the "execute PHP" function handles fatal errors and wraps them
|
143 |
+
// in a valid action response. That fatal error may also be handled by the global fatal error
|
144 |
+
// handler, which also wraps the error in a response. We keep the state in this class, so we
|
145 |
+
// don't send a worker response twice, first time as an action response, second time as a
|
146 |
+
// global response.
|
147 |
+
// If this is to be removed, simply remove fatal error handling from the "execute PHP" action.
|
148 |
+
$lastResponse->send();
|
149 |
+
$this->responseSent = true;
|
150 |
+
}
|
151 |
exit;
|
152 |
}
|
153 |
} elseif ($e !== null) {
|
205 |
spl_autoload_register('mwp_autoload', true, true);
|
206 |
}
|
207 |
|
208 |
+
$GLOBALS['MMB_WORKER_VERSION'] = '4.1.0';
|
209 |
+
$GLOBALS['MMB_WORKER_REVISION'] = '2015-04-23 00:00:00';
|
210 |
$GLOBALS['mmb_plugin_dir'] = WP_PLUGIN_DIR.'/'.basename(dirname(__FILE__));
|
211 |
$GLOBALS['_mmb_item_filter'] = array();
|
212 |
+
$GLOBALS['mmb_core'] = $core = $GLOBALS['mmb_core_backup'] = new MMB_Core();
|
213 |
|
214 |
$siteUrl = function_exists('get_site_option') ? get_site_option('siteurl') : get_option('siteurl');
|
215 |
define('MMB_XFRAME_COOKIE', 'wordpress_'.md5($siteUrl).'_xframe');
|
237 |
// Plugin management hooks.
|
238 |
register_activation_hook(__FILE__, array($core, 'install'));
|
239 |
register_deactivation_hook(__FILE__, array($core, 'deactivate'));
|
240 |
+
register_uninstall_hook(dirname(__FILE__).'/functions.php', 'mwp_uninstall');
|
241 |
|
242 |
// Don't send the "X-Frame-Options: SAMEORIGIN" header if we're logging in inside an iframe.
|
243 |
if (isset($_COOKIE[MMB_XFRAME_COOKIE])) {
|
publickeys/{managewp_mt.pub → ManageWP_mt.pub}
RENAMED
File without changes
|
readme.txt
CHANGED
@@ -12,35 +12,97 @@ ManageWP is the ultimate WordPress productivity tool, allowing you to efficientl
|
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
-
[ManageWP](https://managewp.com/ "Manage WordPress Websites") is a revolutionary service
|
16 |
|
17 |
-
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
* One click upgrades for WordPress, plugin and themes across all your sites
|
22 |
-
* Schedule automatic backups of your websites (Amazon S3, Google Drive, FTP/SFTP and Dropbox supported)
|
23 |
-
* Install WordPress, clone or migrate WordPress website to another domain
|
24 |
-
* One click to access WP admin of any site
|
25 |
-
* Bulk install themes and plugins to multiple sites at once
|
26 |
-
* Bulk publish posts and pages to multiple sites at once
|
27 |
-
* Add sub-users (writers, staff..) to your account
|
28 |
-
* SEO Statistics, track your keyword rankings
|
29 |
-
* Uptime monitoring - receive an SMS notification if your site goes down
|
30 |
|
|
|
|
|
31 |
|
32 |
-
|
|
|
33 |
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
ManageWP is also the creator of [ManageWP.org](https://managewp.org/ "WordPress news site"), community project capturing the pulse of the WordPress community.
|
37 |
|
38 |
== Changelog ==
|
39 |
|
40 |
-
= 4.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
-
- New features for the [ManageWP Orion release](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement")
|
43 |
-
- Misc bug fixes and performance improvements
|
44 |
|
45 |
= 3.9.30 =
|
46 |
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
+
[ManageWP](https://managewp.com/ "Manage Multiple WordPress Websites") is a revolutionary service designed to automate most of your daily tasks when managing multiple WordPress websites, allowing you to use your time on more important matters.
|
16 |
|
17 |
+
= Everything in One Place =
|
18 |
+
Just the hassle of logging into each of your websites is enough to ruin your day. With ManageWP the data from all of your sites is compiled and shown on a single easy to use dashboard, allowing you to check up on your websites in a single glance.
|
19 |
|
20 |
+
= One-click Management =
|
21 |
+
With all the data on a single dashboard, all it takes is one click to perform plugin and theme updates on multiple websites. Got comments? Everything is on one single list. Or maybe you want to clean spam comments, table overhead or post revisions from all of your websites? It takes a single click.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
+
= Backup & Restore =
|
24 |
+
Never leave home without a backup. With the scheduled backup tasks to remote destinations such as Amazon S3, Dropbox and Google Drive you will always have an up-to-date backup which you can use to restore your website if something happened to it (yeah, we know it was YOU who messed up the CSS!)
|
25 |
|
26 |
+
= Quick and Easy Migration =
|
27 |
+
Want to know how easy is to migrate a website with ManageWP? Pick a source website, pick a destination website, click Go. Yeah, it's that easy.
|
28 |
|
29 |
+
= Uptime Monitoring =
|
30 |
+
Be the first to know when your website is down with both email and SMS notifications, and get your website back online before anyone else notices.
|
31 |
+
|
32 |
+
= SEO & Keyword Ranking =
|
33 |
+
Be on top of your website rankings and figure out which keywords work best for you.
|
34 |
+
|
35 |
+
= Client Reports =
|
36 |
+
Keep track of what you're doing for your clients and dazzle them with a summary of your hard work.
|
37 |
+
|
38 |
+
= Is This All? =
|
39 |
+
No way! We've got a bunch of other awesome features, both free and premium, you can check out on our [ManageWP Features & Pricing Page](https://managewp.com/plans-and-pricing "ManageWP Plans & Pricing")
|
40 |
+
|
41 |
+
Check out the [ManageWP promo video](https://www.youtube.com/watch?v=C5nBQJQIfH4).
|
42 |
+
|
43 |
+
https://www.youtube.com/watch?v=C5nBQJQIfH4
|
44 |
|
45 |
ManageWP is also the creator of [ManageWP.org](https://managewp.org/ "WordPress news site"), community project capturing the pulse of the WordPress community.
|
46 |
|
47 |
== Changelog ==
|
48 |
|
49 |
+
= 4.1.0 =
|
50 |
+
|
51 |
+
- New: Incremental backup capability for [ManageWP Orion](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement").
|
52 |
+
|
53 |
+
= 4.0.15 =
|
54 |
+
|
55 |
+
- Fix: Improve compatibility with some plugin updates in [ManageWP Orion](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement").
|
56 |
+
|
57 |
+
= 4.0.14 =
|
58 |
+
|
59 |
+
- Fix: Show custom message when the plugin can not destroy active [ManageWP Orion](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement") sessions when logging out.
|
60 |
+
|
61 |
+
= 4.0.13 =
|
62 |
+
|
63 |
+
- New: Destroy all admin sessions started from [ManageWP Orion](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement") when a user logs out from the dashboard.
|
64 |
+
- Fix: Improve update detection.
|
65 |
+
|
66 |
+
= 4.0.12 =
|
67 |
+
|
68 |
+
- Fix: Improve white-labeling.
|
69 |
+
- Fix: Better compatibility with development builds of WordPress.
|
70 |
+
- Fix: Improve one-click restore functionality on non-English installations of WordPress.
|
71 |
+
|
72 |
+
= 4.0.11 =
|
73 |
+
|
74 |
+
- Fix: Better detect available updates
|
75 |
+
- Fix: Improve compatibility with other plugins
|
76 |
+
|
77 |
+
= 4.0.10 =
|
78 |
+
|
79 |
+
- Fix: Fix update functionality on some installations that use FTP credentials
|
80 |
+
- Fix: Fix Google Drive uploading on installations without cURL PHP extension
|
81 |
+
|
82 |
+
= 4.0.9 =
|
83 |
+
|
84 |
+
- New: Make the ManageWP Worker plugin upgradable through the dashboard widget
|
85 |
+
- Fix: Improve auto-connect functionality with [ManageWP Orion](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement")
|
86 |
+
|
87 |
+
= 4.0.8 =
|
88 |
+
|
89 |
+
- Fix: Fix single-click restore functionality
|
90 |
+
|
91 |
+
= 4.0.7 =
|
92 |
+
|
93 |
+
- Fix: Fix issues related to cloning and backup restoration
|
94 |
+
- Fix: Improve precision of the hit counter
|
95 |
+
- Fix: Improve compatibility with other plugins
|
96 |
+
- Fix: Numerous small improvements and fixes
|
97 |
+
|
98 |
+
= 4.0.5 =
|
99 |
+
|
100 |
+
- Fix: Misc bug fixes and performance improvements
|
101 |
+
|
102 |
+
= 4.0.1 =
|
103 |
|
104 |
+
- New: New features for the [ManageWP Orion release](http://managewp.com/managewp-orion-official-announcement "ManageWP Orion Official Announcement")
|
105 |
+
- Fix: Misc bug fixes and performance improvements
|
106 |
|
107 |
= 3.9.30 =
|
108 |
|
src/Google/IO/Stream.php
CHANGED
@@ -171,4 +171,9 @@ class Google_IO_Stream extends Google_IO_Abstract
|
|
171 |
|
172 |
return self::UNKNOWN_CODE;
|
173 |
}
|
|
|
|
|
|
|
|
|
|
|
174 |
}
|
171 |
|
172 |
return self::UNKNOWN_CODE;
|
173 |
}
|
174 |
+
|
175 |
+
protected function needsQuirk()
|
176 |
+
{
|
177 |
+
return false;
|
178 |
+
}
|
179 |
}
|
src/MMB/Backup.php
CHANGED
@@ -1423,13 +1423,16 @@ class MMB_Backup extends MMB_Core
|
|
1423 |
|
1424 |
$task = $this->tasks[$params['task_name']];
|
1425 |
$backups = $task['task_results'];
|
1426 |
-
$result_id =
|
1427 |
$backup = !empty($backups[$result_id]) ? $backups[$result_id] : false;
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
$
|
1432 |
-
|
|
|
|
|
|
|
1433 |
}
|
1434 |
}
|
1435 |
|
@@ -1547,7 +1550,7 @@ class MMB_Backup extends MMB_Core
|
|
1547 |
);
|
1548 |
|
1549 |
/* Replace options and content urls */
|
1550 |
-
$this->replaceOptionsAndUrls($params['overwrite'], $params['new_user'], $params['new_password'], $params['old_user'], $params['clone_from_url'], $params['admin_email'], $params['mwp_clone'], $oldCredentialsAndOptions, $home
|
1551 |
|
1552 |
$newUrl = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", 'home'));
|
1553 |
$restoreParams['newUrl'] = is_object($newUrl) ? $newUrl->option_value : null;
|
@@ -1785,7 +1788,7 @@ class MMB_Backup extends MMB_Core
|
|
1785 |
}
|
1786 |
}
|
1787 |
|
1788 |
-
private function replaceOptionsAndUrls($overwrite, $newUser, $newPassword, $oldUser, $cloneFromUrl, $adminEmail, $mwpClone, $oldCredentialsAndOptions, $home
|
1789 |
{
|
1790 |
global $wpdb;
|
1791 |
$this->wpdb_reconnect();
|
@@ -1899,9 +1902,6 @@ class MMB_Backup extends MMB_Core
|
|
1899 |
$query = "DELETE FROM ".$new_table_prefix."options WHERE option_name = 'user_hit_count'";
|
1900 |
$wpdb->query($query);
|
1901 |
|
1902 |
-
/* Restore previous backups */
|
1903 |
-
$wpdb->query("UPDATE ".$new_table_prefix."options SET option_value = '".serialize($currentTasksTmp)."' WHERE option_name = 'mwp_backup_tasks'");
|
1904 |
-
|
1905 |
/* Check for .htaccess permalinks update */
|
1906 |
$this->replace_htaccess($home);
|
1907 |
} else {
|
@@ -1950,7 +1950,7 @@ class MMB_Backup extends MMB_Core
|
|
1950 |
if (!mwp_is_shell_available()) {
|
1951 |
throw new MMB_Exception("Shell is not available");
|
1952 |
}
|
1953 |
-
$process = new Symfony_Process_Process($command, untrailingslashit(ABSPATH),
|
1954 |
mwp_logger()->info('Database import process started', array(
|
1955 |
'executable_location' => $mysql,
|
1956 |
'command_line' => $process->getCommandLine(),
|
@@ -4129,7 +4129,7 @@ class MMB_Backup extends MMB_Core
|
|
4129 |
$return = $this->google_drive_backup($account_info['mwp_google_drive']);
|
4130 |
$this->wpdb_reconnect();
|
4131 |
|
4132 |
-
if (!
|
4133 |
$this->update_status($task_name, $this->statuses['google_drive'], true);
|
4134 |
$this->update_status($task_name, $this->statuses['finished'], true);
|
4135 |
}
|
@@ -4137,12 +4137,14 @@ class MMB_Backup extends MMB_Core
|
|
4137 |
|
4138 |
$tasks = $this->tasks;
|
4139 |
@file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
|
4140 |
-
if ($return
|
4141 |
@unlink($backup_file);
|
4142 |
unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
|
4143 |
}
|
4144 |
$this->update_tasks($tasks);
|
4145 |
-
$return
|
|
|
|
|
4146 |
} else {
|
4147 |
$return = array(
|
4148 |
'error' => 'Backup file not found on your server. Please try again.',
|
@@ -4214,8 +4216,15 @@ class MMB_Backup extends MMB_Core
|
|
4214 |
*/
|
4215 |
public function wpdb_reconnect()
|
4216 |
{
|
|
|
4217 |
global $wpdb;
|
4218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
4219 |
if (class_exists('wpdb') && function_exists('wp_set_wpdb_vars')) {
|
4220 |
@mysql_close($wpdb->dbh);
|
4221 |
$wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
|
@@ -4326,6 +4335,31 @@ class MMB_Backup extends MMB_Core
|
|
4326 |
|
4327 |
$this->notifyMyself('mmb_remote_upload', $args);
|
4328 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4329 |
}
|
4330 |
|
4331 |
if (!function_exists('get_all_files_from_dir')) {
|
@@ -4559,6 +4593,9 @@ function restore_migrate_urls()
|
|
4559 |
|
4560 |
function restore_htaccess()
|
4561 |
{
|
|
|
|
|
|
|
4562 |
$htaccessRealpath = realpath(ABSPATH.'.htaccess');
|
4563 |
|
4564 |
if ($htaccessRealpath) {
|
@@ -4568,7 +4605,7 @@ function restore_htaccess()
|
|
4568 |
if (isset($GLOBALS['wp_rewrite'])) {
|
4569 |
$wpRewrite = $GLOBALS['wp_rewrite'];
|
4570 |
} else {
|
4571 |
-
$wpRewrite = new WP_Rewrite();
|
4572 |
}
|
4573 |
|
4574 |
$wpRewrite->flush_rules(true);
|
1423 |
|
1424 |
$task = $this->tasks[$params['task_name']];
|
1425 |
$backups = $task['task_results'];
|
1426 |
+
$result_id = isset($params['result_id']) ? $params['result_id'] : null;
|
1427 |
$backup = !empty($backups[$result_id]) ? $backups[$result_id] : false;
|
1428 |
+
|
1429 |
+
if (!empty($params['resultUuid'])) {
|
1430 |
+
foreach ($backups as $key => $result) {
|
1431 |
+
if ($result['resultUuid'] == $params['resultUuid']) {
|
1432 |
+
$backup = $result;
|
1433 |
+
$result_id = $key;
|
1434 |
+
break;
|
1435 |
+
}
|
1436 |
}
|
1437 |
}
|
1438 |
|
1550 |
);
|
1551 |
|
1552 |
/* Replace options and content urls */
|
1553 |
+
$this->replaceOptionsAndUrls($params['overwrite'], $params['new_user'], $params['new_password'], $params['old_user'], $params['clone_from_url'], $params['admin_email'], $params['mwp_clone'], $oldCredentialsAndOptions, $home);
|
1554 |
|
1555 |
$newUrl = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", 'home'));
|
1556 |
$restoreParams['newUrl'] = is_object($newUrl) ? $newUrl->option_value : null;
|
1788 |
}
|
1789 |
}
|
1790 |
|
1791 |
+
private function replaceOptionsAndUrls($overwrite, $newUser, $newPassword, $oldUser, $cloneFromUrl, $adminEmail, $mwpClone, $oldCredentialsAndOptions, $home)
|
1792 |
{
|
1793 |
global $wpdb;
|
1794 |
$this->wpdb_reconnect();
|
1902 |
$query = "DELETE FROM ".$new_table_prefix."options WHERE option_name = 'user_hit_count'";
|
1903 |
$wpdb->query($query);
|
1904 |
|
|
|
|
|
|
|
1905 |
/* Check for .htaccess permalinks update */
|
1906 |
$this->replace_htaccess($home);
|
1907 |
} else {
|
1950 |
if (!mwp_is_shell_available()) {
|
1951 |
throw new MMB_Exception("Shell is not available");
|
1952 |
}
|
1953 |
+
$process = new Symfony_Process_Process($command, untrailingslashit(ABSPATH), $this->getEnv(), null, 3600);
|
1954 |
mwp_logger()->info('Database import process started', array(
|
1955 |
'executable_location' => $mysql,
|
1956 |
'command_line' => $process->getCommandLine(),
|
4129 |
$return = $this->google_drive_backup($account_info['mwp_google_drive']);
|
4130 |
$this->wpdb_reconnect();
|
4131 |
|
4132 |
+
if (!isset($return['error'])) {
|
4133 |
$this->update_status($task_name, $this->statuses['google_drive'], true);
|
4134 |
$this->update_status($task_name, $this->statuses['finished'], true);
|
4135 |
}
|
4137 |
|
4138 |
$tasks = $this->tasks;
|
4139 |
@file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
|
4140 |
+
if ($return === true && $del_host_file) {
|
4141 |
@unlink($backup_file);
|
4142 |
unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
|
4143 |
}
|
4144 |
$this->update_tasks($tasks);
|
4145 |
+
if (!isset($return['error'])) {
|
4146 |
+
$return = $this->tasks[$task_name]['task_results'][$taskResultKey];
|
4147 |
+
}
|
4148 |
} else {
|
4149 |
$return = array(
|
4150 |
'error' => 'Backup file not found on your server. Please try again.',
|
4216 |
*/
|
4217 |
public function wpdb_reconnect()
|
4218 |
{
|
4219 |
+
/** @var wpdb $wpdb */
|
4220 |
global $wpdb;
|
4221 |
|
4222 |
+
if (is_callable(array($wpdb, 'check_connection'))) {
|
4223 |
+
$wpdb->check_connection();
|
4224 |
+
|
4225 |
+
return;
|
4226 |
+
}
|
4227 |
+
|
4228 |
if (class_exists('wpdb') && function_exists('wp_set_wpdb_vars')) {
|
4229 |
@mysql_close($wpdb->dbh);
|
4230 |
$wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
|
4335 |
|
4336 |
$this->notifyMyself('mmb_remote_upload', $args);
|
4337 |
}
|
4338 |
+
|
4339 |
+
/**
|
4340 |
+
* @return array|null
|
4341 |
+
*/
|
4342 |
+
private function getEnv()
|
4343 |
+
{
|
4344 |
+
$lang = getenv('LANG');
|
4345 |
+
|
4346 |
+
if (preg_match('{^.*\.UTF-?8$}i', $lang)) {
|
4347 |
+
// Allow the environment to be inherited.
|
4348 |
+
return null;
|
4349 |
+
}
|
4350 |
+
|
4351 |
+
if (!$lang) {
|
4352 |
+
$lang = 'en_US';
|
4353 |
+
}
|
4354 |
+
|
4355 |
+
$langParts = explode('.', $lang);
|
4356 |
+
|
4357 |
+
if (!isset($langParts[1]) || $langParts[1] !== 'UTF-8') {
|
4358 |
+
$lang = $langParts[0].'.UTF-8';
|
4359 |
+
}
|
4360 |
+
|
4361 |
+
return array('LANG' => $lang);
|
4362 |
+
}
|
4363 |
}
|
4364 |
|
4365 |
if (!function_exists('get_all_files_from_dir')) {
|
4593 |
|
4594 |
function restore_htaccess()
|
4595 |
{
|
4596 |
+
// This has to be done because it contains the function save_mod_rewrite_rules().
|
4597 |
+
include_once ABSPATH.'wp-admin/includes/admin.php';
|
4598 |
+
|
4599 |
$htaccessRealpath = realpath(ABSPATH.'.htaccess');
|
4600 |
|
4601 |
if ($htaccessRealpath) {
|
4605 |
if (isset($GLOBALS['wp_rewrite'])) {
|
4606 |
$wpRewrite = $GLOBALS['wp_rewrite'];
|
4607 |
} else {
|
4608 |
+
$wpRewrite = $GLOBALS['wp_rewrite'] = new WP_Rewrite();
|
4609 |
}
|
4610 |
|
4611 |
$wpRewrite->flush_rules(true);
|
src/MMB/Core.php
CHANGED
@@ -49,8 +49,8 @@ class MMB_Core extends MMB_Helper
|
|
49 |
{
|
50 |
global $blog_id, $_mmb_item_filter, $_mmb_options;
|
51 |
|
52 |
-
$_mmb_options
|
53 |
-
$_mmb_options
|
54 |
|
55 |
if (is_multisite()) {
|
56 |
$this->mmb_multisite = $blog_id;
|
@@ -290,23 +290,6 @@ EOF;
|
|
290 |
}
|
291 |
}
|
292 |
|
293 |
-
public function unRegisterMustUse($loaderName)
|
294 |
-
{
|
295 |
-
$mustUsePluginDir = rtrim(WPMU_PLUGIN_DIR, '/');
|
296 |
-
$loaderPath = $mustUsePluginDir.'/'.$loaderName;
|
297 |
-
|
298 |
-
if (!file_exists($loaderPath)) {
|
299 |
-
return;
|
300 |
-
}
|
301 |
-
|
302 |
-
$removed = @unlink($loaderPath);
|
303 |
-
|
304 |
-
if (!$removed) {
|
305 |
-
$error = error_get_last();
|
306 |
-
throw new Exception(sprintf('Unable to remove loader: %s', $error['message']));
|
307 |
-
}
|
308 |
-
}
|
309 |
-
|
310 |
/**
|
311 |
* Plugin install callback function
|
312 |
* Check PHP version
|
@@ -380,22 +363,13 @@ EOF;
|
|
380 |
update_option('wrksettings', $options);
|
381 |
}
|
382 |
|
383 |
-
public function uninstall()
|
384 |
-
{
|
385 |
-
try {
|
386 |
-
$this->unRegisterMustUse('0-worker.php');
|
387 |
-
} catch (Exception $e) {
|
388 |
-
mwp_logger()->error('Unable to remove loader', array('exception' => $e));
|
389 |
-
}
|
390 |
-
}
|
391 |
-
|
392 |
/**
|
393 |
* Deletes options for communication with master
|
394 |
*/
|
395 |
public function deactivate($deactivate = false)
|
396 |
{
|
397 |
-
$this->uninstall();
|
398 |
/** @var wpdb $wpdb */
|
|
|
399 |
global $current_user, $wpdb, $_wp_using_ext_object_cache;
|
400 |
$_wp_using_ext_object_cache = false;
|
401 |
|
@@ -483,7 +457,7 @@ EOF;
|
|
483 |
|
484 |
ob_start();
|
485 |
@unlink(dirname(__FILE__));
|
486 |
-
$upgrader = new Plugin_Upgrader();
|
487 |
$result = $upgrader->run(
|
488 |
array(
|
489 |
'package' => $params['download_url'],
|
49 |
{
|
50 |
global $blog_id, $_mmb_item_filter, $_mmb_options;
|
51 |
|
52 |
+
$_mmb_options = get_option('wrksettings');
|
53 |
+
$_mmb_options = !empty($_mmb_options) ? $_mmb_options : array();
|
54 |
|
55 |
if (is_multisite()) {
|
56 |
$this->mmb_multisite = $blog_id;
|
290 |
}
|
291 |
}
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
/**
|
294 |
* Plugin install callback function
|
295 |
* Check PHP version
|
363 |
update_option('wrksettings', $options);
|
364 |
}
|
365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
/**
|
367 |
* Deletes options for communication with master
|
368 |
*/
|
369 |
public function deactivate($deactivate = false)
|
370 |
{
|
|
|
371 |
/** @var wpdb $wpdb */
|
372 |
+
mwp_uninstall();
|
373 |
global $current_user, $wpdb, $_wp_using_ext_object_cache;
|
374 |
$_wp_using_ext_object_cache = false;
|
375 |
|
457 |
|
458 |
ob_start();
|
459 |
@unlink(dirname(__FILE__));
|
460 |
+
$upgrader = new Plugin_Upgrader(mwp_container()->getUpdaterSkin());
|
461 |
$result = $upgrader->run(
|
462 |
array(
|
463 |
'package' => $params['download_url'],
|
src/MMB/Helper.php
CHANGED
@@ -11,24 +11,6 @@ class MMB_Helper
|
|
11 |
|
12 |
public $mmb_multisite;
|
13 |
|
14 |
-
/**
|
15 |
-
* Initializes the file system
|
16 |
-
*/
|
17 |
-
public function init_filesystem()
|
18 |
-
{
|
19 |
-
global $wp_filesystem;
|
20 |
-
|
21 |
-
if (!$wp_filesystem || !is_object($wp_filesystem)) {
|
22 |
-
WP_Filesystem();
|
23 |
-
}
|
24 |
-
|
25 |
-
if (!is_object($wp_filesystem)) {
|
26 |
-
return false;
|
27 |
-
}
|
28 |
-
|
29 |
-
return true;
|
30 |
-
}
|
31 |
-
|
32 |
public function mmb_get_user_info($user_info = false, $info = 'login')
|
33 |
{
|
34 |
if ($user_info === false) {
|
@@ -107,21 +89,9 @@ class MMB_Helper
|
|
107 |
return $this->mmb_get_sitemeta_transient($option_name);
|
108 |
}
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
if (version_compare($wp_version, '2.7.9', '<=')) {
|
113 |
-
return get_option($option_name);
|
114 |
-
} else {
|
115 |
-
if (version_compare($wp_version, '2.9.9', '<=')) {
|
116 |
-
$transient = get_option('_transient_'.$option_name);
|
117 |
-
|
118 |
-
return apply_filters("transient_".$option_name, $transient);
|
119 |
-
} else {
|
120 |
-
$transient = get_option('_site_transient_'.$option_name);
|
121 |
|
122 |
-
|
123 |
-
}
|
124 |
-
}
|
125 |
}
|
126 |
|
127 |
public function mmb_delete_transient($option_name)
|
@@ -130,17 +100,7 @@ class MMB_Helper
|
|
130 |
return;
|
131 |
}
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
if (version_compare($wp_version, '2.7.9', '<=')) {
|
136 |
-
delete_option($option_name);
|
137 |
-
} else {
|
138 |
-
if (version_compare($wp_version, '2.9.9', '<=')) {
|
139 |
-
delete_option('_transient_'.$option_name);
|
140 |
-
} else {
|
141 |
-
delete_option('_site_transient_'.$option_name);
|
142 |
-
}
|
143 |
-
}
|
144 |
}
|
145 |
|
146 |
public function mmb_get_sitemeta_transient($option_name)
|
@@ -323,46 +283,6 @@ class MMB_Helper
|
|
323 |
return $crypted;
|
324 |
}
|
325 |
|
326 |
-
public function check_if_user_exists($username = false)
|
327 |
-
{
|
328 |
-
global $wpdb;
|
329 |
-
|
330 |
-
if (empty($username)) {
|
331 |
-
return false;
|
332 |
-
}
|
333 |
-
|
334 |
-
if (!function_exists('username_exists')) {
|
335 |
-
require_once ABSPATH.WPINC.'/registration.php';
|
336 |
-
}
|
337 |
-
|
338 |
-
require_once ABSPATH.'wp-includes/pluggable.php';
|
339 |
-
|
340 |
-
if (username_exists($username) == null) {
|
341 |
-
return false;
|
342 |
-
}
|
343 |
-
|
344 |
-
$user = (array) $this->mmb_get_user_info($username);
|
345 |
-
if (
|
346 |
-
(isset($user[$wpdb->prefix.'user_level']) && $user[$wpdb->prefix.'user_level'] == 10)
|
347 |
-
|| isset($user[$wpdb->prefix.'capabilities']['administrator'])
|
348 |
-
|| (isset($user['caps']['administrator']) && $user['caps']['administrator'] == 1)
|
349 |
-
) {
|
350 |
-
return true;
|
351 |
-
}
|
352 |
-
|
353 |
-
return false;
|
354 |
-
}
|
355 |
-
|
356 |
-
public function refresh_updates()
|
357 |
-
{
|
358 |
-
if (rand(1, 3) == '2') {
|
359 |
-
require_once ABSPATH.WPINC.'/update.php';
|
360 |
-
wp_update_plugins();
|
361 |
-
wp_update_themes();
|
362 |
-
wp_version_check();
|
363 |
-
}
|
364 |
-
}
|
365 |
-
|
366 |
public function remove_http($url = '')
|
367 |
{
|
368 |
if ($url == 'http://' or $url == 'https://') {
|
@@ -401,23 +321,6 @@ class MMB_Helper
|
|
401 |
}
|
402 |
}
|
403 |
|
404 |
-
public function return_bytes($val)
|
405 |
-
{
|
406 |
-
$val = trim($val);
|
407 |
-
$last = strtolower($val[strlen($val) - 1]);
|
408 |
-
switch ($last) {
|
409 |
-
// The 'G' modifier is available since PHP 5.1.0
|
410 |
-
case 'g':
|
411 |
-
$val *= 1024;
|
412 |
-
case 'm':
|
413 |
-
$val *= 1024;
|
414 |
-
case 'k':
|
415 |
-
$val *= 1024;
|
416 |
-
}
|
417 |
-
|
418 |
-
return $val;
|
419 |
-
}
|
420 |
-
|
421 |
public function w3tc_flush($flushAll = false)
|
422 |
{
|
423 |
if ($flushAll) {
|
@@ -468,19 +371,4 @@ class MMB_Helper
|
|
468 |
|
469 |
return $users_authors;
|
470 |
}
|
471 |
-
|
472 |
-
private function verifySignature($data, $signature, $publicKey)
|
473 |
-
{
|
474 |
-
if (function_exists('openssl_verify')) {
|
475 |
-
return (openssl_verify($data, $signature, $publicKey) === 1);
|
476 |
-
}
|
477 |
-
|
478 |
-
require_once dirname(__FILE__).'/../PHPSecLib/Crypt/RSA.php';
|
479 |
-
$rsa = new Crypt_RSA();
|
480 |
-
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
|
481 |
-
$rsa->loadKey($publicKey);
|
482 |
-
$verify = $rsa->verify($data, $signature);
|
483 |
-
|
484 |
-
return $verify;
|
485 |
-
}
|
486 |
}
|
11 |
|
12 |
public $mmb_multisite;
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
public function mmb_get_user_info($user_info = false, $info = 'login')
|
15 |
{
|
16 |
if ($user_info === false) {
|
89 |
return $this->mmb_get_sitemeta_transient($option_name);
|
90 |
}
|
91 |
|
92 |
+
$transient = get_option('_site_transient_'.$option_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
+
return apply_filters("site_transient_".$option_name, $transient);
|
|
|
|
|
95 |
}
|
96 |
|
97 |
public function mmb_delete_transient($option_name)
|
100 |
return;
|
101 |
}
|
102 |
|
103 |
+
delete_option('_site_transient_'.$option_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
|
106 |
public function mmb_get_sitemeta_transient($option_name)
|
283 |
return $crypted;
|
284 |
}
|
285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
public function remove_http($url = '')
|
287 |
{
|
288 |
if ($url == 'http://' or $url == 'https://') {
|
321 |
}
|
322 |
}
|
323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
public function w3tc_flush($flushAll = false)
|
325 |
{
|
326 |
if ($flushAll) {
|
371 |
|
372 |
return $users_authors;
|
373 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
}
|
src/MMB/Installer.php
CHANGED
@@ -84,10 +84,8 @@ class MMB_Installer extends MMB_Core
|
|
84 |
include_once ABSPATH.'wp-admin/includes/class-wp-upgrader.php';
|
85 |
}
|
86 |
|
87 |
-
$
|
88 |
-
$
|
89 |
-
|
90 |
-
$upgrader = new WP_Upgrader($upgrader_skin);
|
91 |
$destination = $type == 'themes' ? WP_CONTENT_DIR.'/themes' : WP_PLUGIN_DIR;
|
92 |
$clear_destination = isset($clear_destination) ? $clear_destination : false;
|
93 |
|
@@ -160,6 +158,18 @@ class MMB_Installer extends MMB_Core
|
|
160 |
@ob_clean();
|
161 |
$this->mmb_maintenance_mode(false);
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
return $install_info;
|
164 |
}
|
165 |
|
@@ -329,7 +339,7 @@ class MMB_Installer extends MMB_Core
|
|
329 |
include_once ABSPATH.'wp-admin/includes/class-wp-upgrader.php';
|
330 |
}
|
331 |
|
332 |
-
$core = new Core_Upgrader();
|
333 |
$result = $core->upgrade($current_update);
|
334 |
$this->mmb_maintenance_mode(false);
|
335 |
if (is_wp_error($result)) {
|
@@ -466,8 +476,8 @@ class MMB_Installer extends MMB_Core
|
|
466 |
}
|
467 |
}
|
468 |
$return = array();
|
469 |
-
if (class_exists('Plugin_Upgrader')
|
470 |
-
$upgrader = new Plugin_Upgrader(
|
471 |
$result = $upgrader->bulk_upgrade(array_keys($plugins));
|
472 |
if (!function_exists('wp_update_plugins')) {
|
473 |
include_once ABSPATH.'wp-includes/update.php';
|
@@ -483,7 +493,6 @@ class MMB_Installer extends MMB_Core
|
|
483 |
if (!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)) {
|
484 |
$return[$plugin_slug] = 1;
|
485 |
} else {
|
486 |
-
update_option('mmb_forcerefresh', true);
|
487 |
$return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
|
488 |
}
|
489 |
}
|
@@ -524,8 +533,8 @@ class MMB_Installer extends MMB_Core
|
|
524 |
}
|
525 |
}
|
526 |
}
|
527 |
-
if (class_exists('Theme_Upgrader')
|
528 |
-
$upgrader = new Theme_Upgrader(
|
529 |
$result = $upgrader->bulk_upgrade($themes);
|
530 |
|
531 |
if (!function_exists('wp_update_themes')) {
|
@@ -543,7 +552,6 @@ class MMB_Installer extends MMB_Core
|
|
543 |
if (!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)) {
|
544 |
$return[$theme_tmp] = 1;
|
545 |
} else {
|
546 |
-
update_option('mmb_forcerefresh', true);
|
547 |
$return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
|
548 |
}
|
549 |
}
|
@@ -659,7 +667,7 @@ class MMB_Installer extends MMB_Core
|
|
659 |
$upgrader_skin = new WP_Upgrader_Skin();
|
660 |
$upgrader_skin->done_header = true;
|
661 |
$upgrader = new WP_Upgrader();
|
662 |
-
@$update_result
|
663 |
array(
|
664 |
'package' => $update['url'],
|
665 |
'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR.'/themes' : WP_PLUGIN_DIR,
|
@@ -712,10 +720,6 @@ class MMB_Installer extends MMB_Core
|
|
712 |
include_once ABSPATH.'wp-admin/includes/plugin.php';
|
713 |
}
|
714 |
foreach ($current->response as $plugin_path => $plugin_data) {
|
715 |
-
if ($plugin_path == 'worker/init.php') {
|
716 |
-
continue;
|
717 |
-
}
|
718 |
-
|
719 |
$data = get_plugin_data(WP_PLUGIN_DIR.'/'.$plugin_path);
|
720 |
if (isset($data['Name']) && in_array($data['Name'], $filter)) {
|
721 |
continue;
|
@@ -745,7 +749,7 @@ class MMB_Installer extends MMB_Core
|
|
745 |
$current = $this->mmb_get_transient('update_themes');
|
746 |
if (!empty($current->response)) {
|
747 |
foreach ((array) $all_themes as $theme_template => $theme_data) {
|
748 |
-
if (
|
749 |
continue;
|
750 |
}
|
751 |
|
84 |
include_once ABSPATH.'wp-admin/includes/class-wp-upgrader.php';
|
85 |
}
|
86 |
|
87 |
+
$upgrader = new WP_Upgrader(mwp_container()->getUpdaterSkin());
|
88 |
+
$upgrader->init();
|
|
|
|
|
89 |
$destination = $type == 'themes' ? WP_CONTENT_DIR.'/themes' : WP_PLUGIN_DIR;
|
90 |
$clear_destination = isset($clear_destination) ? $clear_destination : false;
|
91 |
|
158 |
@ob_clean();
|
159 |
$this->mmb_maintenance_mode(false);
|
160 |
|
161 |
+
if (mwp_container()->getRequestStack()->getMasterRequest()->getProtocol() >= 1) {
|
162 |
+
// WP_Error won't get JSON encoded, so unwrap the error here.
|
163 |
+
foreach ($install_info as $key => $value) {
|
164 |
+
if ($value instanceof WP_Error) {
|
165 |
+
$install_info[$key] = array(
|
166 |
+
'error' => $value->get_error_message(),
|
167 |
+
'code' => $value->get_error_code(),
|
168 |
+
);
|
169 |
+
}
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
return $install_info;
|
174 |
}
|
175 |
|
339 |
include_once ABSPATH.'wp-admin/includes/class-wp-upgrader.php';
|
340 |
}
|
341 |
|
342 |
+
$core = new Core_Upgrader(mwp_container()->getUpdaterSkin());
|
343 |
$result = $core->upgrade($current_update);
|
344 |
$this->mmb_maintenance_mode(false);
|
345 |
if (is_wp_error($result)) {
|
476 |
}
|
477 |
}
|
478 |
$return = array();
|
479 |
+
if (class_exists('Plugin_Upgrader')) {
|
480 |
+
$upgrader = new Plugin_Upgrader(mwp_container()->getUpdaterSkin());
|
481 |
$result = $upgrader->bulk_upgrade(array_keys($plugins));
|
482 |
if (!function_exists('wp_update_plugins')) {
|
483 |
include_once ABSPATH.'wp-includes/update.php';
|
493 |
if (!empty($result[$plugin_slug]) || (isset($current->checked[$plugin_slug]) && version_compare(array_search($plugin_slug, $versions), $current->checked[$plugin_slug], '<') == true)) {
|
494 |
$return[$plugin_slug] = 1;
|
495 |
} else {
|
|
|
496 |
$return[$plugin_slug] = 'Could not refresh upgrade transients, please reload website data';
|
497 |
}
|
498 |
}
|
533 |
}
|
534 |
}
|
535 |
}
|
536 |
+
if (class_exists('Theme_Upgrader')) {
|
537 |
+
$upgrader = new Theme_Upgrader(mwp_container()->getUpdaterSkin());
|
538 |
$result = $upgrader->bulk_upgrade($themes);
|
539 |
|
540 |
if (!function_exists('wp_update_themes')) {
|
552 |
if (!empty($result[$theme_tmp]) || (isset($current->checked[$theme_tmp]) && version_compare(array_search($theme_tmp, $versions), $current->checked[$theme_tmp], '<') == true)) {
|
553 |
$return[$theme_tmp] = 1;
|
554 |
} else {
|
|
|
555 |
$return[$theme_tmp] = 'Could not refresh upgrade transients, please reload website data';
|
556 |
}
|
557 |
}
|
667 |
$upgrader_skin = new WP_Upgrader_Skin();
|
668 |
$upgrader_skin->done_header = true;
|
669 |
$upgrader = new WP_Upgrader();
|
670 |
+
@$update_result = $upgrader->run(
|
671 |
array(
|
672 |
'package' => $update['url'],
|
673 |
'destination' => isset($update['type']) && $update['type'] == 'theme' ? WP_CONTENT_DIR.'/themes' : WP_PLUGIN_DIR,
|
720 |
include_once ABSPATH.'wp-admin/includes/plugin.php';
|
721 |
}
|
722 |
foreach ($current->response as $plugin_path => $plugin_data) {
|
|
|
|
|
|
|
|
|
723 |
$data = get_plugin_data(WP_PLUGIN_DIR.'/'.$plugin_path);
|
724 |
if (isset($data['Name']) && in_array($data['Name'], $filter)) {
|
725 |
continue;
|
749 |
$current = $this->mmb_get_transient('update_themes');
|
750 |
if (!empty($current->response)) {
|
751 |
foreach ((array) $all_themes as $theme_template => $theme_data) {
|
752 |
+
if (!empty($theme_data['Parent Theme'])) {
|
753 |
continue;
|
754 |
}
|
755 |
|
src/MMB/Stats.php
CHANGED
@@ -25,11 +25,11 @@ class MMB_Stats extends MMB_Core
|
|
25 |
}
|
26 |
|
27 |
if (!empty($options['approvedComments'])) {
|
28 |
-
$siteStatistics['approvedComments'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$prefix}comments WHERE comment_approved='1'");
|
29 |
}
|
30 |
|
31 |
if (!empty($options['activePlugins'])) {
|
32 |
-
$siteStatistics['activePlugins'] = count((array)
|
33 |
}
|
34 |
|
35 |
if (!empty($options['publishedPosts'])) {
|
@@ -391,27 +391,18 @@ class MMB_Stats extends MMB_Core
|
|
391 |
include_once ABSPATH.'wp-admin/includes/update.php';
|
392 |
|
393 |
$stats = $this->mmb_parse_action_params('pre_init_stats', $params, $this);
|
394 |
-
|
395 |
-
|
396 |
-
if (function_exists('w3tc_pgcache_flush') || function_exists('wp_cache_clear_cache')) {
|
397 |
-
$this->mmb_delete_transient('update_core');
|
398 |
-
$this->mmb_delete_transient('update_plugins');
|
399 |
-
$this->mmb_delete_transient('update_themes');
|
400 |
-
@wp_version_check();
|
401 |
-
@wp_update_plugins();
|
402 |
-
@wp_update_themes();
|
403 |
-
}
|
404 |
|
405 |
if ($params['refresh'] == 'transient') {
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
@wp_version_check();
|
411 |
-
@wp_update_plugins();
|
412 |
-
@wp_update_themes();
|
413 |
-
}
|
414 |
}
|
|
|
|
|
|
|
|
|
415 |
}
|
416 |
|
417 |
/** @var $wpdb wpdb */
|
@@ -433,6 +424,8 @@ class MMB_Stats extends MMB_Core
|
|
433 |
$stats['blog_public'] = get_option('blog_public');
|
434 |
$stats['timezone'] = get_option('timezone_string');
|
435 |
$stats['timezone_offset'] = get_option('gmt_offset');
|
|
|
|
|
436 |
|
437 |
if (!function_exists('get_filesystem_method')) {
|
438 |
include_once ABSPATH.'wp-admin/includes/file.php';
|
25 |
}
|
26 |
|
27 |
if (!empty($options['approvedComments'])) {
|
28 |
+
$siteStatistics['approvedComments'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$prefix}comments c INNER JOIN {$prefix}posts p ON c.comment_post_ID = p.ID WHERE comment_approved = '1' AND p.post_status = 'publish'");
|
29 |
}
|
30 |
|
31 |
if (!empty($options['activePlugins'])) {
|
32 |
+
$siteStatistics['activePlugins'] = count((array) get_option('active_plugins', array()));
|
33 |
}
|
34 |
|
35 |
if (!empty($options['publishedPosts'])) {
|
391 |
include_once ABSPATH.'wp-admin/includes/update.php';
|
392 |
|
393 |
$stats = $this->mmb_parse_action_params('pre_init_stats', $params, $this);
|
394 |
+
extract($params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
|
396 |
if ($params['refresh'] == 'transient') {
|
397 |
+
if (function_exists('w3tc_pgcache_flush') || function_exists('wp_cache_clear_cache')) {
|
398 |
+
$this->mmb_delete_transient('update_core');
|
399 |
+
$this->mmb_delete_transient('update_plugins');
|
400 |
+
$this->mmb_delete_transient('update_themes');
|
|
|
|
|
|
|
|
|
401 |
}
|
402 |
+
|
403 |
+
wp_version_check();
|
404 |
+
wp_update_plugins();
|
405 |
+
wp_update_themes();
|
406 |
}
|
407 |
|
408 |
/** @var $wpdb wpdb */
|
424 |
$stats['blog_public'] = get_option('blog_public');
|
425 |
$stats['timezone'] = get_option('timezone_string');
|
426 |
$stats['timezone_offset'] = get_option('gmt_offset');
|
427 |
+
$stats['server_ip'] = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : null;
|
428 |
+
$stats['hostname'] = php_uname('n');
|
429 |
|
430 |
if (!function_exists('get_filesystem_method')) {
|
431 |
include_once ABSPATH.'wp-admin/includes/file.php';
|
src/MWP/Action/DestroySessions.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_DestroySessions extends MWP_Action_Abstract
|
12 |
+
{
|
13 |
+
public function execute()
|
14 |
+
{
|
15 |
+
$store = $this->container->getSessionStore();
|
16 |
+
|
17 |
+
return array(
|
18 |
+
'destroyed' => $store->destroyAll(),
|
19 |
+
);
|
20 |
+
}
|
21 |
+
}
|
src/MWP/Action/GetState.php
CHANGED
@@ -16,6 +16,10 @@ class MWP_Action_GetState extends MWP_Action_Abstract
|
|
16 |
|
17 |
const COMMENTS = 'comments';
|
18 |
|
|
|
|
|
|
|
|
|
19 |
const PLUGINS = 'plugins';
|
20 |
|
21 |
const THEMES = 'themes';
|
@@ -41,11 +45,9 @@ class MWP_Action_GetState extends MWP_Action_Abstract
|
|
41 |
$queryResult = $this->getField($queryInfo['type'], $queryInfo['options']);
|
42 |
$end = sprintf("%.6f", microtime(true) - $start);
|
43 |
$result[$fieldName] = array(
|
44 |
-
'type'
|
45 |
-
'
|
46 |
-
'
|
47 |
-
'result' => $queryResult,
|
48 |
-
'resultCount' => count($queryResult),
|
49 |
);
|
50 |
}
|
51 |
|
@@ -61,6 +63,10 @@ class MWP_Action_GetState extends MWP_Action_Abstract
|
|
61 |
return $this->getPosts($options);
|
62 |
case self::COMMENTS:
|
63 |
return $this->getComments($options);
|
|
|
|
|
|
|
|
|
64 |
case self::PLUGINS:
|
65 |
return $this->getPlugins($options);
|
66 |
case self::THEMES:
|
@@ -107,6 +113,24 @@ class MWP_Action_GetState extends MWP_Action_Abstract
|
|
107 |
return $comments;
|
108 |
}
|
109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
protected function getPlugins(array $options = array())
|
111 |
{
|
112 |
$options += array(
|
16 |
|
17 |
const COMMENTS = 'comments';
|
18 |
|
19 |
+
const SQL_RESULT = 'sqlResult';
|
20 |
+
|
21 |
+
const SINGLE_SQL_RESULT = 'singleSqlResult';
|
22 |
+
|
23 |
const PLUGINS = 'plugins';
|
24 |
|
25 |
const THEMES = 'themes';
|
45 |
$queryResult = $this->getField($queryInfo['type'], $queryInfo['options']);
|
46 |
$end = sprintf("%.6f", microtime(true) - $start);
|
47 |
$result[$fieldName] = array(
|
48 |
+
'type' => $queryInfo['type'],
|
49 |
+
'benchmark' => $end,
|
50 |
+
'result' => $queryResult,
|
|
|
|
|
51 |
);
|
52 |
}
|
53 |
|
63 |
return $this->getPosts($options);
|
64 |
case self::COMMENTS:
|
65 |
return $this->getComments($options);
|
66 |
+
case self::SQL_RESULT:
|
67 |
+
return $this->getSqlResult($options);
|
68 |
+
case self::SINGLE_SQL_RESULT:
|
69 |
+
return $this->getSingleSqlResult($options);
|
70 |
case self::PLUGINS:
|
71 |
return $this->getPlugins($options);
|
72 |
case self::THEMES:
|
113 |
return $comments;
|
114 |
}
|
115 |
|
116 |
+
protected function getSingleSqlResult(array $options = array())
|
117 |
+
{
|
118 |
+
$options += array(
|
119 |
+
'query' => null,
|
120 |
+
);
|
121 |
+
|
122 |
+
return $this->container->getWordPressContext()->getDb()->get_var($options['query']);
|
123 |
+
}
|
124 |
+
|
125 |
+
protected function getSqlResult(array $options = array())
|
126 |
+
{
|
127 |
+
$options += array(
|
128 |
+
'query' => null,
|
129 |
+
);
|
130 |
+
|
131 |
+
return $this->container->getWordPressContext()->getDb()->get_results($options['query']);
|
132 |
+
}
|
133 |
+
|
134 |
protected function getPlugins(array $options = array())
|
135 |
{
|
136 |
$options += array(
|
src/MWP/Action/IncrementalBackup/Abstract.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_Abstract extends MWP_Action_Abstract
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @param array $result
|
15 |
+
*
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
protected function createResult(array $result)
|
19 |
+
{
|
20 |
+
return array(
|
21 |
+
'result' => $result,
|
22 |
+
'server' => $this->getServerStatistics()->toArray(),
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Get file real path given a path relative to WordPress root.
|
28 |
+
*
|
29 |
+
* @param $relativePath
|
30 |
+
*
|
31 |
+
* @return string
|
32 |
+
*/
|
33 |
+
protected function getRealPath($relativePath)
|
34 |
+
{
|
35 |
+
return realpath(untrailingslashit(ABSPATH).'/'.$relativePath);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return MWP_IncrementalBackup_Model_ServerStatistics
|
40 |
+
*/
|
41 |
+
private function getServerStatistics()
|
42 |
+
{
|
43 |
+
return MWP_IncrementalBackup_Model_ServerStatistics::factory();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @param $files
|
48 |
+
*
|
49 |
+
* @return array
|
50 |
+
*/
|
51 |
+
protected function replaceWindowsPaths($files)
|
52 |
+
{
|
53 |
+
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
54 |
+
foreach ($files as $key => $file) {
|
55 |
+
$files[$key]['path'] = str_replace('\\', '/', $file['path']);
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
return $files;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @param $path
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
protected function replaceWindowsPath($path)
|
68 |
+
{
|
69 |
+
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
70 |
+
$path = str_replace('\\', '/', $path);
|
71 |
+
}
|
72 |
+
|
73 |
+
return $path;
|
74 |
+
}
|
75 |
+
}
|
src/MWP/Action/IncrementalBackup/ChecksumTables.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_ChecksumTables extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
|
14 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
15 |
+
{
|
16 |
+
$query = implode(',', $params['query']);
|
17 |
+
|
18 |
+
$wpdb = $this->container->getWordPressContext()->getDb();
|
19 |
+
$results = $wpdb->get_results('CHECKSUM TABLE '.$query, ARRAY_A);
|
20 |
+
$checksum = array();
|
21 |
+
|
22 |
+
foreach ($results as $row) {
|
23 |
+
$checksum[$row['Table']] = $row['Checksum'];
|
24 |
+
}
|
25 |
+
|
26 |
+
return $this->createResult(array('checksum' => $checksum, 'db' => $this->container->getWordPressContext()->getConstant('DB_NAME')));
|
27 |
+
}
|
28 |
+
}
|
src/MWP/Action/IncrementalBackup/DumpTables.php
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_DumpTables extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
const METHOD_MYSQLDUMP = 'mysqldump';
|
14 |
+
const METHOD_PHPDUMPER = 'phpdumper';
|
15 |
+
|
16 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
17 |
+
{
|
18 |
+
$method = $params['method'];
|
19 |
+
$tables = $params['tables'];
|
20 |
+
|
21 |
+
$this->assertTablesExist($tables);
|
22 |
+
|
23 |
+
if (isset($params['options']) && is_array($params['options'])) {
|
24 |
+
$options = $params['options'];
|
25 |
+
} else {
|
26 |
+
$options = array();
|
27 |
+
}
|
28 |
+
|
29 |
+
$dumper = $this->getDumper($method, $options);
|
30 |
+
|
31 |
+
try {
|
32 |
+
$stream = $dumper->dump($tables);
|
33 |
+
} catch (Exception $e) {
|
34 |
+
if ($e instanceof MWP_Worker_Exception) {
|
35 |
+
throw $e;
|
36 |
+
}
|
37 |
+
|
38 |
+
// Convert any other exception to MWP_Worker_Exception
|
39 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::BACKUP_DATABASE_FAILED, $e->getMessage(), array(
|
40 |
+
'code' => $e->getCode(),
|
41 |
+
'message' => $e->getMessage(),
|
42 |
+
'type' => get_class($e),
|
43 |
+
));
|
44 |
+
}
|
45 |
+
|
46 |
+
$file = new MWP_IncrementalBackup_Model_File();
|
47 |
+
$file->setPathname('tables.sql');
|
48 |
+
$file->setStream($stream);
|
49 |
+
|
50 |
+
$result = new MWP_IncrementalBackup_Model_FetchFilesResult();
|
51 |
+
$result->setServerStatistics(MWP_IncrementalBackup_Model_ServerStatistics::factory());
|
52 |
+
$result->setFiles(array($file));
|
53 |
+
|
54 |
+
return $result;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param array $tables
|
59 |
+
*
|
60 |
+
* @throws MWP_Worker_Exception
|
61 |
+
*/
|
62 |
+
private function assertTablesExist(array $tables)
|
63 |
+
{
|
64 |
+
$rows = mwp_context()->getDb()->get_results("SHOW TABLES", ARRAY_N);
|
65 |
+
foreach ($rows as $row) {
|
66 |
+
// $row is always an array with only a single member
|
67 |
+
$table = $row[0];
|
68 |
+
|
69 |
+
$index = array_search($table, $tables);
|
70 |
+
if ($index !== false) {
|
71 |
+
// Remove from $tables - don't worry, $tables has not been passed by reference :)
|
72 |
+
array_splice($tables, $index, 1);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
// Tables which have not been found are located in $tables
|
77 |
+
if (count($tables)) {
|
78 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::BACKUP_DATABASE_MISSING_TABLES, "Some tables are missing", array(
|
79 |
+
// Return an array of missing tables
|
80 |
+
'tables' => $tables,
|
81 |
+
));
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @param string $method
|
87 |
+
*
|
88 |
+
* @param array $options
|
89 |
+
*
|
90 |
+
* @throws MWP_Worker_Exception
|
91 |
+
* @return MWP_IncrementalBackup_Database_DumperInterface
|
92 |
+
*/
|
93 |
+
private function getDumper($method, array $options = array())
|
94 |
+
{
|
95 |
+
$dumperOptions = MWP_IncrementalBackup_Database_DumpOptions::createFromArray($options);
|
96 |
+
|
97 |
+
switch ($method) {
|
98 |
+
case self::METHOD_MYSQLDUMP:
|
99 |
+
$configuration = MWP_IncrementalBackup_Database_Configuration::createFromWordPressContext(mwp_context());
|
100 |
+
$dumper = new MWP_IncrementalBackup_Database_MysqlDumpDumper($configuration, $dumperOptions);
|
101 |
+
|
102 |
+
return $dumper;
|
103 |
+
case self::METHOD_PHPDUMPER:
|
104 |
+
$configuration = MWP_IncrementalBackup_Database_Configuration::createFromWordPressContext(mwp_context());
|
105 |
+
$dumper = new MWP_IncrementalBackup_Database_PhpDumper($configuration, mwp_container()->getSystemEnvironment(), $dumperOptions);
|
106 |
+
|
107 |
+
return $dumper;
|
108 |
+
default:
|
109 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::BACKUP_DATABASE_METHOD_NOT_AVAILABLE);
|
110 |
+
break;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
src/MWP/Action/IncrementalBackup/FetchFiles.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_FetchFiles extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
|
14 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* Each file is structured like:
|
18 |
+
* [
|
19 |
+
* "relativePath" => file path relative to ABSPATH,
|
20 |
+
* "size" => file size sent for reference,
|
21 |
+
* "offset" => number of bytes to offset hash start (integer, optional, default 0),
|
22 |
+
* "limit" => number of bytes to hash (integer, optional, default 0),
|
23 |
+
* ]
|
24 |
+
*/
|
25 |
+
$requestedFiles = $params['files'];
|
26 |
+
|
27 |
+
$result = new MWP_IncrementalBackup_Model_FetchFilesResult();
|
28 |
+
|
29 |
+
foreach ($requestedFiles as $requestedFile) {
|
30 |
+
$relativePath = $requestedFile['relativePath'];
|
31 |
+
$realPath = $this->getRealPath($relativePath);
|
32 |
+
$offset = isset($requestedFile['offset']) ? $requestedFile['offset'] : 0;
|
33 |
+
$limit = isset($requestedFile['limit']) ? $requestedFile['limit'] : -1;
|
34 |
+
|
35 |
+
$file = new MWP_IncrementalBackup_Model_File();
|
36 |
+
$file->setPathname($requestedFile['relativePath']);
|
37 |
+
$file->setStream(new MWP_Stream_Limit(new MWP_Stream_LazyFile($realPath), $offset, $limit));
|
38 |
+
$result->addFile($file);
|
39 |
+
}
|
40 |
+
|
41 |
+
$result->setServerStatistics(MWP_IncrementalBackup_Model_ServerStatistics::factory());
|
42 |
+
|
43 |
+
return $result;
|
44 |
+
}
|
45 |
+
}
|
src/MWP/Action/IncrementalBackup/HashFiles.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_HashFiles extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
// 100MB
|
14 |
+
const UNIX_HASH_THRESHOLD = 104857600;
|
15 |
+
|
16 |
+
// 100KB
|
17 |
+
const MAX_CHUNK_SIZE = 102400;
|
18 |
+
|
19 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
20 |
+
{
|
21 |
+
$hashComputer = new MWP_IncrementalBackup_HashComputer();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Each file is structured like:
|
25 |
+
* [
|
26 |
+
* "relativePath" => file path relative to ABSPATH,
|
27 |
+
* "size" => file size sent for reference,
|
28 |
+
* "offset" => number of bytes to offset hash start (integer, optional, default 0),
|
29 |
+
* "limit" => number of bytes to hash (integer, optional, default 0),
|
30 |
+
* "forcePartialHashing" => partially hashes file instead of md5_file always (boolean, optional, default false),
|
31 |
+
* ]
|
32 |
+
*/
|
33 |
+
$files = $params['files'];
|
34 |
+
$result = array();
|
35 |
+
|
36 |
+
// Allow overriding max chunk byte size per request for doing partial hashes
|
37 |
+
$chunkByteSize = isset($params['maxChunkByteSize']) ? $params['maxChunkByteSize'] : self::MAX_CHUNK_SIZE;
|
38 |
+
$hashComputer->setMaxChunkByteSize($chunkByteSize);
|
39 |
+
|
40 |
+
$unixHashThreshold = isset($params['unixMd5Threshold']) ? $params['unixMd5Threshold'] : self::UNIX_HASH_THRESHOLD;
|
41 |
+
|
42 |
+
foreach ($files as $file) {
|
43 |
+
$relativePath = $file['path'];
|
44 |
+
$size = $file['size'];
|
45 |
+
$offset = isset($file['offset']) ? $file['offset'] : 0;
|
46 |
+
$limit = isset($file['limit']) ? $file['limit'] : 0;
|
47 |
+
$forcePartial = isset($file['forcePartialHashing']) ? $file['forcePartialHashing'] : false;
|
48 |
+
$realPath = $this->getRealPath($relativePath);
|
49 |
+
|
50 |
+
// Run a unix command to generate md5 hash if file size exceeds threshold
|
51 |
+
// Ignore partial requests for big files because of speed problems
|
52 |
+
if ($size > $unixHashThreshold && $offset === 0 && $limit === 0) {
|
53 |
+
$hash = $hashComputer->computeUnixMd5Sum($realPath);
|
54 |
+
|
55 |
+
if ($hash !== null) {
|
56 |
+
$result[] = array(
|
57 |
+
'path' => $relativePath,
|
58 |
+
'hash' => $hash,
|
59 |
+
);
|
60 |
+
|
61 |
+
continue;
|
62 |
+
}
|
63 |
+
// In case of a failed hashing fall back bellow to compute md5 hash from PHP
|
64 |
+
}
|
65 |
+
|
66 |
+
$hash = $hashComputer->computeMd5Hash($realPath, $offset, $limit, $forcePartial);
|
67 |
+
$result[] = array(
|
68 |
+
'path' => $relativePath,
|
69 |
+
'hash' => $hash,
|
70 |
+
);
|
71 |
+
}
|
72 |
+
|
73 |
+
return $this->createResult(array(
|
74 |
+
'files' => $result,
|
75 |
+
));
|
76 |
+
}
|
77 |
+
}
|
src/MWP/Action/IncrementalBackup/ListFiles.php
ADDED
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/*
|
12 |
+
* This file is part of the ManageWP Worker plugin.
|
13 |
+
*
|
14 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
15 |
+
*
|
16 |
+
* For the full copyright and license information, please view the LICENSE
|
17 |
+
* file that was distributed with this source code.
|
18 |
+
*/
|
19 |
+
|
20 |
+
class MWP_Action_IncrementalBackup_ListFiles extends MWP_Action_IncrementalBackup_Abstract
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Return a list of all files
|
24 |
+
*
|
25 |
+
* @param array $params
|
26 |
+
* @param MWP_Worker_Request $request
|
27 |
+
*
|
28 |
+
* @return array
|
29 |
+
*/
|
30 |
+
public function queryFiles(array $params = array(), MWP_Worker_Request $request)
|
31 |
+
{
|
32 |
+
if (isset($params['query']) && is_array($params['query'])) {
|
33 |
+
$files = $this->getFilesInfo($params['query']);
|
34 |
+
} else {
|
35 |
+
$files = $this->listFiles(ABSPATH, true);
|
36 |
+
}
|
37 |
+
|
38 |
+
$files = $this->replaceWindowsPaths($files);
|
39 |
+
|
40 |
+
return $this->createResult(array('files' => $files));
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @param array $params
|
45 |
+
* @param MWP_Worker_Request $request
|
46 |
+
*
|
47 |
+
* @return array
|
48 |
+
*/
|
49 |
+
public function listDirectories(array $params = array(), MWP_Worker_Request $request)
|
50 |
+
{
|
51 |
+
$directories = $params['directories'];
|
52 |
+
|
53 |
+
$result = array();
|
54 |
+
|
55 |
+
foreach ($directories as $directory) {
|
56 |
+
$path = $directory['path'];
|
57 |
+
$recursive = isset($directory['recursive']) ? $directory['recursive'] : false;
|
58 |
+
$offset = isset($directory['offset']) ? $directory['offset'] : 0;
|
59 |
+
$limit = isset($directory['limit']) ? $directory['limit'] : 0;
|
60 |
+
|
61 |
+
$realPath = $this->getRealPath($path);
|
62 |
+
if (!file_exists($realPath)) {
|
63 |
+
$result[$path] = false;
|
64 |
+
continue;
|
65 |
+
}
|
66 |
+
|
67 |
+
$filesInDirectory = $this->listFiles($realPath, $recursive, $offset, $limit);
|
68 |
+
$filesInDirectory = $this->replaceWindowsPaths($filesInDirectory);
|
69 |
+
$result[$this->replaceWindowsPath($path)] = $filesInDirectory;
|
70 |
+
}
|
71 |
+
|
72 |
+
return $this->createResult(array('directories' => $result));
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Return a list of files in the WordPress root directory, recursively
|
77 |
+
*
|
78 |
+
* @param string $rootPath
|
79 |
+
* @param bool $recursive
|
80 |
+
* @param int $offset
|
81 |
+
* @param int $limit
|
82 |
+
*
|
83 |
+
* @return array
|
84 |
+
*/
|
85 |
+
private function listFiles($rootPath, $recursive = false, $offset = 0, $limit = 0)
|
86 |
+
{
|
87 |
+
$result = array();
|
88 |
+
|
89 |
+
$iterator = $this->createIterator($recursive, $rootPath);
|
90 |
+
|
91 |
+
$i = 0;
|
92 |
+
|
93 |
+
foreach ($iterator as $file) {
|
94 |
+
if ($i++ < $offset) {
|
95 |
+
continue;
|
96 |
+
}
|
97 |
+
|
98 |
+
if ($limit !== 0 && $i > $offset + $limit) {
|
99 |
+
break;
|
100 |
+
}
|
101 |
+
|
102 |
+
/** @var SplFileInfo $file */
|
103 |
+
$fileResult = $this->createFileResult($file);
|
104 |
+
|
105 |
+
$result[] = $fileResult;
|
106 |
+
}
|
107 |
+
|
108 |
+
return $result;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Get a list of file stats for given $files
|
113 |
+
*
|
114 |
+
* @param array $files
|
115 |
+
*
|
116 |
+
* @return array
|
117 |
+
*/
|
118 |
+
protected function getFilesInfo(array $files)
|
119 |
+
{
|
120 |
+
$result = array();
|
121 |
+
|
122 |
+
foreach ($files as $path) {
|
123 |
+
$realPath = $this->getRealPath($path);
|
124 |
+
|
125 |
+
if (!file_exists($realPath)) {
|
126 |
+
$result[] = array(
|
127 |
+
'path' => $path,
|
128 |
+
'exists' => false,
|
129 |
+
);
|
130 |
+
continue;
|
131 |
+
}
|
132 |
+
|
133 |
+
$file = new SplFileInfo($realPath);
|
134 |
+
$result[] = $this->createFileResult($file);
|
135 |
+
}
|
136 |
+
|
137 |
+
return $result;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @param string $realPath
|
142 |
+
* @param string $rootPath
|
143 |
+
*
|
144 |
+
* @return string
|
145 |
+
*/
|
146 |
+
private function getRelativePath($realPath, $rootPath)
|
147 |
+
{
|
148 |
+
if ($realPath === untrailingslashit($rootPath)) {
|
149 |
+
return '.';
|
150 |
+
} else {
|
151 |
+
$relative = str_replace(untrailingslashit($rootPath).'/', '', $realPath);
|
152 |
+
if ($relative == $realPath) {
|
153 |
+
$up = '';
|
154 |
+
while (($pos = strpos($realPath, $rootPath)) === false) {
|
155 |
+
$rootPath = dirname($rootPath);
|
156 |
+
$up .= '../';
|
157 |
+
}
|
158 |
+
|
159 |
+
return $up.substr($realPath, $pos + strlen($rootPath) + 1);
|
160 |
+
} else {
|
161 |
+
return $relative;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param SplFileInfo $file
|
168 |
+
*
|
169 |
+
* @return array
|
170 |
+
*/
|
171 |
+
private function createFileResult(SplFileInfo $file)
|
172 |
+
{
|
173 |
+
$fileResult = array(
|
174 |
+
'path' => $this->getRelativePath($file->getRealPath(), ABSPATH),
|
175 |
+
'size' => $file->getSize(),
|
176 |
+
'isDirectory' => $file->isDir(),
|
177 |
+
'isLink' => $file->isLink(),
|
178 |
+
'owner' => $file->getOwner(),
|
179 |
+
'group' => $file->getGroup(),
|
180 |
+
'permissions' => $file->getPerms(),
|
181 |
+
'exists' => true,
|
182 |
+
);
|
183 |
+
|
184 |
+
if ($file->isLink()) {
|
185 |
+
$fileResult['linkTarget'] = $file->getLinkTarget();
|
186 |
+
};
|
187 |
+
|
188 |
+
return $fileResult;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Create a recursive or non-recursive iterator for $path. Handles php 5.2 incompatiblity.
|
193 |
+
*
|
194 |
+
* @param bool $recursive
|
195 |
+
* @param string $path
|
196 |
+
*
|
197 |
+
* @return Iterator
|
198 |
+
*/
|
199 |
+
private function createIterator($recursive, $path)
|
200 |
+
{
|
201 |
+
if ($recursive) {
|
202 |
+
// PHP 5.2.x does not have the SKIP_DOTS flag because it skips all dots by default
|
203 |
+
// The behavior was changed in PHP 5.3+ and it does not skip dots without the SKIP_DOTS flag
|
204 |
+
$php52 = version_compare(phpversion(), '5.3', '<');
|
205 |
+
|
206 |
+
if ($php52) {
|
207 |
+
$directory = new RecursiveDirectoryIterator($path);
|
208 |
+
} else {
|
209 |
+
$directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
|
210 |
+
}
|
211 |
+
|
212 |
+
$iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
|
213 |
+
} else {
|
214 |
+
$directory = new Symfony_Filesystem_FilesystemIterator($path, FilesystemIterator::SKIP_DOTS);
|
215 |
+
$iterator = new IteratorIterator($directory);
|
216 |
+
}
|
217 |
+
|
218 |
+
return $iterator;
|
219 |
+
}
|
220 |
+
}
|
src/MWP/Action/IncrementalBackup/ListTables.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_ListTables extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
|
14 |
+
public function listTables(array $params = array(), MWP_Worker_Request $request)
|
15 |
+
{
|
16 |
+
$wpdb = $this->container->getWordPressContext()->getDb();
|
17 |
+
$db = $this->container->getWordPressContext()->getConstant('DB_NAME');
|
18 |
+
$tables = $wpdb->get_results($wpdb->prepare('SELECT table_name AS "table", data_length as size FROM information_schema.TABLES WHERE table_schema = %s', $db), ARRAY_A);
|
19 |
+
|
20 |
+
return $this->createResult(array('tables' => $tables, 'db_prefix' => $wpdb->prefix));
|
21 |
+
}
|
22 |
+
}
|
src/MWP/Action/IncrementalBackup/Stats.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_Stats extends MWP_Action_IncrementalBackup_Abstract
|
12 |
+
{
|
13 |
+
|
14 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
15 |
+
{
|
16 |
+
|
17 |
+
$wpdb = $this->container->getWordPressContext()->getDb();
|
18 |
+
$getState = new MWP_Action_GetState();
|
19 |
+
$getState->setContainer($this->container);
|
20 |
+
$themesKey = MWP_Action_GetState::THEMES;
|
21 |
+
$themes = $getState->execute(array($themesKey => array('type' => $themesKey, 'options' => array())));
|
22 |
+
$pluginsKey = MWP_Action_GetState::PLUGINS;
|
23 |
+
$plugins = $getState->execute(array($pluginsKey => array('type' => $pluginsKey, 'options' => array())));
|
24 |
+
$statistics = array();
|
25 |
+
$statistics['themes'] = count($themes[$themesKey]['result']);
|
26 |
+
$statistics['plugins'] = count($plugins[$pluginsKey]['result']);
|
27 |
+
$statistics['posts'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type='post'");
|
28 |
+
$statistics['pages'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type='page'");
|
29 |
+
$statistics['uploads'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type='attachment'");
|
30 |
+
$statistics['comments'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->comments}");
|
31 |
+
$statistics['latest_post_title'] = $wpdb->get_var("SELECT post_title FROM {$wpdb->posts} WHERE post_type='post' AND post_status='publish' ORDER BY ID DESC LIMIT 1");
|
32 |
+
$statistics['wp_version'] = $this->container->getWordPressContext()->getVersion();
|
33 |
+
$currentTheme = $this->container->getWordPressContext()->getCurrentTheme();
|
34 |
+
$statistics['active_theme'] = $currentTheme['Name'].' v'.$currentTheme['Version'];
|
35 |
+
$statistics['platform'] = strtoupper(substr(PHP_OS, 0, 3));
|
36 |
+
|
37 |
+
if (!empty($params['file_count'])) {
|
38 |
+
$paths = !empty($params['file_paths']) ? $params['file_paths'] : array(ABSPATH);
|
39 |
+
$pathSize = array();
|
40 |
+
foreach ($paths as $path) {
|
41 |
+
$pathSize[$path] = $this->getFileCount($path);
|
42 |
+
}
|
43 |
+
$statistics['file_count'] = $pathSize;
|
44 |
+
}
|
45 |
+
|
46 |
+
return $this->createResult(array('statistic' => $statistics));
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param $path
|
51 |
+
*
|
52 |
+
* @return int
|
53 |
+
*/
|
54 |
+
private function getFileCount($path)
|
55 |
+
{
|
56 |
+
$size = 0;
|
57 |
+
$ignore = array('.', '..');
|
58 |
+
$files = scandir($path);
|
59 |
+
foreach ($files as $file) {
|
60 |
+
if (in_array($file, $ignore)) {
|
61 |
+
continue;
|
62 |
+
}
|
63 |
+
if (is_dir(rtrim($path, '/').'/'.$file)) {
|
64 |
+
$size += $this->getFileCount(rtrim($path, '/').'/'.$file);
|
65 |
+
} else {
|
66 |
+
$size++;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
return $size;
|
71 |
+
}
|
72 |
+
}
|
src/MWP/Action/IncrementalBackup/UploadCloner.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Action_IncrementalBackup_UploadCloner extends MWP_Action_Abstract
|
12 |
+
{
|
13 |
+
public function execute(array $params = array(), MWP_Worker_Request $request)
|
14 |
+
{
|
15 |
+
$files = $params['files'];
|
16 |
+
|
17 |
+
$rootPath = ABSPATH;
|
18 |
+
$filesystem = new Symfony_Filesystem_Filesystem();
|
19 |
+
|
20 |
+
try {
|
21 |
+
foreach ($files as $file) {
|
22 |
+
$realpath = $rootPath.$file['pathname'];
|
23 |
+
if ($file['dir'] === true) {
|
24 |
+
$filesystem->mkdir($realpath);
|
25 |
+
} else {
|
26 |
+
$filesystem->dumpFile($realpath, $file['contents']);
|
27 |
+
}
|
28 |
+
}
|
29 |
+
} catch (Symfony_Filesystem_Exception_IOException $e) {
|
30 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::IO_EXCEPTION, $e->getMessage());
|
31 |
+
}
|
32 |
+
|
33 |
+
return array();
|
34 |
+
}
|
35 |
+
}
|
src/MWP/Backup/ArrayHelper.php
CHANGED
@@ -14,4 +14,19 @@ class MWP_Backup_ArrayHelper
|
|
14 |
{
|
15 |
return is_array($array) && array_key_exists($key, $array) ? $array[$key] : $default;
|
16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
14 |
{
|
15 |
return is_array($array) && array_key_exists($key, $array) ? $array[$key] : $default;
|
16 |
}
|
17 |
+
|
18 |
+
public static function arrayColumn($array, $columnIndex = 0)
|
19 |
+
{
|
20 |
+
$result = array();
|
21 |
+
foreach ($array as $arr) {
|
22 |
+
if (!is_array($arr)) {
|
23 |
+
continue;
|
24 |
+
}
|
25 |
+
|
26 |
+
$arr = array_values($arr);
|
27 |
+
$result[] = $arr[$columnIndex];
|
28 |
+
}
|
29 |
+
|
30 |
+
return $result;
|
31 |
+
}
|
32 |
}
|
src/MWP/Backup/MysqlDump/QuerySequenceDump.php
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
|
11 |
class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlDump
|
12 |
{
|
|
|
13 |
/** @var Resource File Pointer */
|
14 |
protected $file;
|
15 |
|
@@ -19,7 +20,7 @@ class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlD
|
|
19 |
public function dumpToFile()
|
20 |
{
|
21 |
$writer = $this->getWriter();
|
22 |
-
$allTables = $this->getConnection()->query('SHOW TABLES')->fetchAll(
|
23 |
$tables = array_intersect($allTables, $this->getOptions('tables', $allTables));
|
24 |
|
25 |
$writer->open();
|
@@ -40,7 +41,7 @@ class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlD
|
|
40 |
foreach ($tables as $tableName) {
|
41 |
// Get the SHOW CREATE TABLE part
|
42 |
$content = $this->getConnection()
|
43 |
-
->query("SHOW CREATE TABLE `{$tableName}`;"
|
44 |
->fetchAll();
|
45 |
if (is_array($content)) {
|
46 |
foreach ($content as $entry) {
|
@@ -59,7 +60,7 @@ class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlD
|
|
59 |
}
|
60 |
|
61 |
$columns = $this->getConnection()
|
62 |
-
->query("SHOW COLUMNS IN `{$tableName}`;"
|
63 |
->fetchAll();
|
64 |
|
65 |
if (is_array($columns)) {
|
@@ -67,7 +68,7 @@ class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlD
|
|
67 |
}
|
68 |
|
69 |
$allData = $this->getConnection()
|
70 |
-
->query($this->selectAllDataQuery($tableName, $columns)
|
71 |
|
72 |
// Go through row by row
|
73 |
if (!$this->getOptions('skip_lock_tables')) {
|
10 |
|
11 |
class MWP_Backup_MysqlDump_QuerySequenceDump extends MWP_Backup_MysqlDump_MysqlDump
|
12 |
{
|
13 |
+
|
14 |
/** @var Resource File Pointer */
|
15 |
protected $file;
|
16 |
|
20 |
public function dumpToFile()
|
21 |
{
|
22 |
$writer = $this->getWriter();
|
23 |
+
$allTables = MWP_Backup_ArrayHelper::arrayColumn($this->getConnection()->query('SHOW TABLES')->fetchAll());
|
24 |
$tables = array_intersect($allTables, $this->getOptions('tables', $allTables));
|
25 |
|
26 |
$writer->open();
|
41 |
foreach ($tables as $tableName) {
|
42 |
// Get the SHOW CREATE TABLE part
|
43 |
$content = $this->getConnection()
|
44 |
+
->query("SHOW CREATE TABLE `{$tableName}`;")
|
45 |
->fetchAll();
|
46 |
if (is_array($content)) {
|
47 |
foreach ($content as $entry) {
|
60 |
}
|
61 |
|
62 |
$columns = $this->getConnection()
|
63 |
+
->query("SHOW COLUMNS IN `{$tableName}`;")
|
64 |
->fetchAll();
|
65 |
|
66 |
if (is_array($columns)) {
|
68 |
}
|
69 |
|
70 |
$allData = $this->getConnection()
|
71 |
+
->query($this->selectAllDataQuery($tableName, $columns));
|
72 |
|
73 |
// Go through row by row
|
74 |
if (!$this->getOptions('skip_lock_tables')) {
|
src/MWP/Event/ActionRequest.php
CHANGED
@@ -21,10 +21,13 @@ class MWP_Event_ActionRequest extends Symfony_EventDispatcher_Event
|
|
21 |
*/
|
22 |
private $params;
|
23 |
|
24 |
-
|
|
|
|
|
25 |
{
|
26 |
$this->request = $request;
|
27 |
$this->params = $params;
|
|
|
28 |
}
|
29 |
|
30 |
/**
|
@@ -50,4 +53,12 @@ class MWP_Event_ActionRequest extends Symfony_EventDispatcher_Event
|
|
50 |
{
|
51 |
$this->params = $params;
|
52 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
}
|
21 |
*/
|
22 |
private $params;
|
23 |
|
24 |
+
private $actionDefinition;
|
25 |
+
|
26 |
+
public function __construct(MWP_Worker_Request $request, array $params, MWP_Action_Definition $actionDefinition)
|
27 |
{
|
28 |
$this->request = $request;
|
29 |
$this->params = $params;
|
30 |
+
$this->actionDefinition = $actionDefinition;
|
31 |
}
|
32 |
|
33 |
/**
|
53 |
{
|
54 |
$this->params = $params;
|
55 |
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @return MWP_Action_Definition
|
59 |
+
*/
|
60 |
+
public function getActionDefinition()
|
61 |
+
{
|
62 |
+
return $this->actionDefinition;
|
63 |
+
}
|
64 |
}
|
src/MWP/EventListener/ActionException/MultipartException.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_ActionException_MultipartException extends MWP_EventListener_ActionException_SetExceptionData
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
private $boundary;
|
18 |
+
|
19 |
+
public function __construct($boundary)
|
20 |
+
{
|
21 |
+
$this->boundary = $boundary;
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function getSubscribedEvents()
|
25 |
+
{
|
26 |
+
return array(
|
27 |
+
MWP_Event_Events::ACTION_EXCEPTION => array('onActionException', 300),
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function onActionException(MWP_Event_ActionException $event)
|
32 |
+
{
|
33 |
+
if ($event->getRequest()->getAction() !== 'fetch_files' && $event->getRequest()->getAction() !== 'dump_tables') {
|
34 |
+
return;
|
35 |
+
}
|
36 |
+
|
37 |
+
$event->stopPropagation();
|
38 |
+
parent::onActionException($event);
|
39 |
+
|
40 |
+
$parts = array();
|
41 |
+
|
42 |
+
$parts[] = new MWP_Http_MultipartResponsePart(
|
43 |
+
array(
|
44 |
+
'content-type' => 'application/json',
|
45 |
+
'x-mwp-error' => 'error',
|
46 |
+
),
|
47 |
+
json_encode($event->getData())
|
48 |
+
);
|
49 |
+
|
50 |
+
$event->setResponse(new MWP_Http_MultipartResponse($parts, $this->boundary));
|
51 |
+
}
|
52 |
+
}
|
src/MWP/EventListener/ActionRequest/LogRequest.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_ActionRequest_LogRequest implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $logger;
|
15 |
+
|
16 |
+
public function __construct(Monolog_Logger $logger)
|
17 |
+
{
|
18 |
+
$this->logger = $logger;
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getSubscribedEvents()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
MWP_Event_Events::ACTION_REQUEST => array('onActionRequest', -200),
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function onActionRequest(MWP_Event_ActionRequest $event)
|
29 |
+
{
|
30 |
+
$request = $event->getRequest();
|
31 |
+
$this->logger->debug('Master request: "{action}"', array(
|
32 |
+
'action' => $request->getAction(),
|
33 |
+
'params' => $request->getParams(),
|
34 |
+
'setting' => $request->getSetting(),
|
35 |
+
));
|
36 |
+
}
|
37 |
+
}
|
src/MWP/EventListener/{MasterRequest → ActionRequest}/SetCurrentUser.php
RENAMED
@@ -8,7 +8,7 @@
|
|
8 |
* file that was distributed with this source code.
|
9 |
*/
|
10 |
|
11 |
-
class
|
12 |
{
|
13 |
|
14 |
private $context;
|
@@ -21,18 +21,34 @@ class MWP_EventListener_MasterRequest_SetCurrentUser implements Symfony_EventDis
|
|
21 |
public static function getSubscribedEvents()
|
22 |
{
|
23 |
return array(
|
24 |
-
MWP_Event_Events::
|
25 |
);
|
26 |
}
|
27 |
|
28 |
-
public function
|
29 |
{
|
30 |
if (!$event->getRequest()->isAuthenticated()) {
|
31 |
return;
|
32 |
}
|
33 |
|
34 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
$user = null;
|
|
|
36 |
|
37 |
if ($usernameUsed) {
|
38 |
$user = $this->context->getUserByUsername($usernameUsed);
|
@@ -48,17 +64,5 @@ class MWP_EventListener_MasterRequest_SetCurrentUser implements Symfony_EventDis
|
|
48 |
}
|
49 |
|
50 |
$this->context->setCurrentUser($user);
|
51 |
-
|
52 |
-
/*
|
53 |
-
if (isset($user)) {
|
54 |
-
wp_set_current_user($user->ID);
|
55 |
-
// Compatibility with All In One Security
|
56 |
-
update_user_meta($user->ID, 'last_login_time', current_time('mysql'));
|
57 |
-
}
|
58 |
-
|
59 |
-
if (defined('ALTERNATE_WP_CRON') && !defined('DOING_AJAX') && ALTERNATE_WP_CRON === true) {
|
60 |
-
define('DOING_AJAX', true);
|
61 |
-
}
|
62 |
-
*/
|
63 |
}
|
64 |
}
|
8 |
* file that was distributed with this source code.
|
9 |
*/
|
10 |
|
11 |
+
class MWP_EventListener_ActionRequest_SetCurrentUser implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
{
|
13 |
|
14 |
private $context;
|
21 |
public static function getSubscribedEvents()
|
22 |
{
|
23 |
return array(
|
24 |
+
MWP_Event_Events::ACTION_REQUEST => array('onActionRequest', -300),
|
25 |
);
|
26 |
}
|
27 |
|
28 |
+
public function onActionRequest(MWP_Event_ActionRequest $event)
|
29 |
{
|
30 |
if (!$event->getRequest()->isAuthenticated()) {
|
31 |
return;
|
32 |
}
|
33 |
|
34 |
+
$actionHook = $event->getActionDefinition()->getOption('hook_name');
|
35 |
+
|
36 |
+
if ($actionHook) {
|
37 |
+
// Set the user on the earliest hook after pluggable.php is loaded.
|
38 |
+
$hookProxy = new MWP_WordPress_HookProxy(array($this, 'setCurrentUserFromEvent'), $event);
|
39 |
+
$this->context->addAction('plugins_loaded', $hookProxy->getCallable(), -9999);
|
40 |
+
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
|
44 |
+
// We're inside the MU context, so set the user immediately.
|
45 |
+
$this->setCurrentUserFromEvent($event);
|
46 |
+
}
|
47 |
+
|
48 |
+
public function setCurrentUserFromEvent(MWP_Event_ActionRequest $event)
|
49 |
+
{
|
50 |
$user = null;
|
51 |
+
$usernameUsed = $event->getRequest()->getUsername();
|
52 |
|
53 |
if ($usernameUsed) {
|
54 |
$user = $this->context->getUserByUsername($usernameUsed);
|
64 |
}
|
65 |
|
66 |
$this->context->setCurrentUser($user);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
}
|
src/MWP/EventListener/ActionRequest/SetSettings.php
CHANGED
@@ -13,9 +13,12 @@ class MWP_EventListener_ActionRequest_SetSettings implements Symfony_EventDispat
|
|
13 |
|
14 |
private $context;
|
15 |
|
16 |
-
|
|
|
|
|
17 |
{
|
18 |
$this->context = $context;
|
|
|
19 |
}
|
20 |
|
21 |
public static function getSubscribedEvents()
|
@@ -29,10 +32,91 @@ class MWP_EventListener_ActionRequest_SetSettings implements Symfony_EventDispat
|
|
29 |
{
|
30 |
set_time_limit(1800);
|
31 |
|
|
|
|
|
32 |
$this->context->set('_wp_using_ext_object_cache', false);
|
33 |
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
if (empty($data['setting'])) {
|
37 |
return;
|
38 |
}
|
13 |
|
14 |
private $context;
|
15 |
|
16 |
+
private $system;
|
17 |
+
|
18 |
+
public function __construct(MWP_WordPress_Context $context, MWP_System_Environment $system)
|
19 |
{
|
20 |
$this->context = $context;
|
21 |
+
$this->system = $system;
|
22 |
}
|
23 |
|
24 |
public static function getSubscribedEvents()
|
32 |
{
|
33 |
set_time_limit(1800);
|
34 |
|
35 |
+
$this->setMemoryLimit();
|
36 |
+
|
37 |
$this->context->set('_wp_using_ext_object_cache', false);
|
38 |
|
39 |
+
// Alternate WP cron can run on 'init' hook.
|
40 |
+
$this->context->removeAction('init', 'wp_cron');
|
41 |
+
|
42 |
+
$this->saveWorkerConfiguration($event->getRequest()->getData());
|
43 |
+
|
44 |
+
$this->resetVersions($event);
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Reset WordPress core versions, because a certain "security" plugin can modify it
|
49 |
+
* and break other plugins. Only do this for master requests.
|
50 |
+
*
|
51 |
+
* @param MWP_Event_ActionRequest $event
|
52 |
+
*/
|
53 |
+
private function resetVersions(MWP_Event_ActionRequest $event)
|
54 |
+
{
|
55 |
+
$actionHook = $event->getActionDefinition()->getOption('hook_name');
|
56 |
+
|
57 |
+
if ($actionHook) {
|
58 |
+
// Set the user on the earliest hook after pluggable.php is loaded.
|
59 |
+
$hookProxy = new MWP_WordPress_HookProxy(array($this, 'requireVersions'));
|
60 |
+
$this->context->addAction('init', $hookProxy->getCallable(), 11);
|
61 |
|
62 |
+
return;
|
63 |
+
}
|
64 |
+
|
65 |
+
$this->requireVersions();
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Callback for version resetting, has to work with PHP 5.2.
|
70 |
+
*
|
71 |
+
* @internal
|
72 |
+
*/
|
73 |
+
public function requireVersions()
|
74 |
+
{
|
75 |
+
$versionFile = $this->context->getConstant('ABSPATH').$this->context->getConstant('WPINC').'/version.php';
|
76 |
+
if (!file_exists($versionFile)) {
|
77 |
+
// For whatever reason.
|
78 |
+
return;
|
79 |
+
}
|
80 |
+
|
81 |
+
include $versionFile;
|
82 |
+
|
83 |
+
$varNames = array(
|
84 |
+
'wp_version',
|
85 |
+
'wp_db_version',
|
86 |
+
'tinymce_version',
|
87 |
+
'required_php_version',
|
88 |
+
'required_mysql_version',
|
89 |
+
);
|
90 |
+
|
91 |
+
foreach ($varNames as $varName) {
|
92 |
+
if (!isset($$varName)) {
|
93 |
+
continue;
|
94 |
+
}
|
95 |
+
$this->context->set($varName, $$varName);
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* By default, WordPress sets limits of 40MB for regular installations and 60MB for multi-sites.
|
101 |
+
* If the limit is lower, try to increase it a bit here.
|
102 |
+
*/
|
103 |
+
private function setMemoryLimit()
|
104 |
+
{
|
105 |
+
if ($this->context->isMultisite()) {
|
106 |
+
$wantedLimit = 60 * 1024 * 1024;
|
107 |
+
} else {
|
108 |
+
$wantedLimit = 40 * 1024 * 1024;
|
109 |
+
}
|
110 |
+
|
111 |
+
$memoryLimit = $this->system->getMemoryLimit();
|
112 |
+
|
113 |
+
if ($memoryLimit !== -1 && $memoryLimit < $wantedLimit) {
|
114 |
+
ini_set('memory_limit', $wantedLimit);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
private function saveWorkerConfiguration(array $data)
|
119 |
+
{
|
120 |
if (empty($data['setting'])) {
|
121 |
return;
|
122 |
}
|
src/MWP/EventListener/ActionResponse/FetchFiles.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Registered by MWP_Action_IncrementalBackup_FetchFiles and MWP_Action_IncrementalBackup_DumpTables actions
|
13 |
+
*/
|
14 |
+
class MWP_EventListener_ActionResponse_FetchFiles implements Symfony_EventDispatcher_EventSubscriberInterface
|
15 |
+
{
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
private $boundary;
|
21 |
+
|
22 |
+
public function __construct($boundary)
|
23 |
+
{
|
24 |
+
$this->boundary = $boundary;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Set MWP_Action_IncrementalBackup_FetchFiles action response
|
29 |
+
*/
|
30 |
+
public function onActionResponse(MWP_Event_ActionResponse $event)
|
31 |
+
{
|
32 |
+
if ($event->getRequest()->getAction() !== 'fetch_files' && $event->getRequest()->getAction() !== 'dump_tables') {
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
// Prevent other listeners from hijacking this response
|
37 |
+
$event->stopPropagation();
|
38 |
+
|
39 |
+
/** @var MWP_IncrementalBackup_Model_FetchFilesResult $result */
|
40 |
+
$result = $event->getData();
|
41 |
+
|
42 |
+
$parts = array();
|
43 |
+
|
44 |
+
$parts[] = new MWP_Http_MultipartResponsePart(
|
45 |
+
array('content-type' => 'application/json'),
|
46 |
+
json_encode($result->getServerStatistics()->toArray())
|
47 |
+
);
|
48 |
+
|
49 |
+
foreach ($result->getFiles() as $file) {
|
50 |
+
$parts[] = new MWP_Http_MultipartResponsePart(
|
51 |
+
array(
|
52 |
+
'content-type' => 'application/octet-stream',
|
53 |
+
'content-location' => $file->getPathname(),
|
54 |
+
),
|
55 |
+
$file->getStream()
|
56 |
+
);
|
57 |
+
}
|
58 |
+
|
59 |
+
$event->setResponse(new MWP_Http_MultipartResponse($parts, $this->boundary));
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* {@inheritdoc}
|
64 |
+
**/
|
65 |
+
public static function getSubscribedEvents()
|
66 |
+
{
|
67 |
+
return array(
|
68 |
+
MWP_Event_Events::ACTION_RESPONSE => array('onActionResponse', 200),
|
69 |
+
);
|
70 |
+
}
|
71 |
+
}
|
src/MWP/EventListener/ActionResponse/SetLegacyPhpExecutionData.php
CHANGED
@@ -44,8 +44,6 @@ class MWP_EventListener_ActionResponse_SetLegacyPhpExecutionData implements Symf
|
|
44 |
throw new MWP_Worker_Exception(MWP_Worker_Exception::PHP_EVAL_ERROR, sprintf('Fatal error [%s]: %s in %s on line %d', self::$errorMap[$data['fatalError']['type']], $data['fatalError']['message'], $data['fatalError']['file'], $data['fatalError']['line']));
|
45 |
}
|
46 |
|
47 |
-
|
48 |
-
$event->setData($data['output']);
|
49 |
-
}
|
50 |
}
|
51 |
}
|
44 |
throw new MWP_Worker_Exception(MWP_Worker_Exception::PHP_EVAL_ERROR, sprintf('Fatal error [%s]: %s in %s on line %d', self::$errorMap[$data['fatalError']['type']], $data['fatalError']['message'], $data['fatalError']['file'], $data['fatalError']['line']));
|
45 |
}
|
46 |
|
47 |
+
$event->setData(isset($data['output']) ? $data['output'] : '');
|
|
|
|
|
48 |
}
|
49 |
}
|
src/MWP/EventListener/ActionResponse/SetLegacyWebsiteConnectionData.php
CHANGED
@@ -36,20 +36,24 @@ class MWP_EventListener_ActionResponse_SetLegacyWebsiteConnectionData implements
|
|
36 |
return;
|
37 |
}
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
if (!array_key_exists('notifications', $params)) {
|
42 |
-
// This is not a legacy call.
|
43 |
return;
|
44 |
}
|
45 |
|
|
|
|
|
46 |
$this->context->requireWpRewrite();
|
47 |
$this->context->requireTaxonomies();
|
48 |
$this->context->requirePostTypes();
|
49 |
$this->context->requireTheme();
|
|
|
50 |
|
51 |
$stats = new MMB_Stats();
|
52 |
-
|
|
|
|
|
|
|
|
|
53 |
$event->setData($stats->get_initial_stats());
|
54 |
}
|
55 |
}
|
36 |
return;
|
37 |
}
|
38 |
|
39 |
+
if ($event->getRequest()->getProtocol() >= 100) {
|
|
|
|
|
|
|
40 |
return;
|
41 |
}
|
42 |
|
43 |
+
$params = $event->getRequest()->getParams();
|
44 |
+
|
45 |
$this->context->requireWpRewrite();
|
46 |
$this->context->requireTaxonomies();
|
47 |
$this->context->requirePostTypes();
|
48 |
$this->context->requireTheme();
|
49 |
+
$this->context->requireCookieConstants();
|
50 |
|
51 |
$stats = new MMB_Stats();
|
52 |
+
|
53 |
+
if (!empty($params['notifications'])) {
|
54 |
+
$this->context->optionSet('mwp_notifications', $params['notifications']);
|
55 |
+
}
|
56 |
+
|
57 |
$event->setData($stats->get_initial_stats());
|
58 |
}
|
59 |
}
|
src/MWP/EventListener/ActionResponse/SetUpdaterLog.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_ActionResponse_SetUpdaterLog implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $updaterSkin;
|
15 |
+
|
16 |
+
function __construct(MWP_Updater_TraceableUpdaterSkin $updaterSkin)
|
17 |
+
{
|
18 |
+
$this->updaterSkin = $updaterSkin;
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getSubscribedEvents()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
MWP_Event_Events::ACTION_RESPONSE => 'onActionResponse',
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function onActionResponse(MWP_Event_ActionResponse $event)
|
29 |
+
{
|
30 |
+
$response = $event->getResponse();
|
31 |
+
|
32 |
+
if ($response === null) {
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
$messages = $this->updaterSkin->get_upgrade_messages();
|
37 |
+
|
38 |
+
if (!$messages) {
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
|
42 |
+
$data = $response->getContent();
|
43 |
+
$data['updaterLog'] = $messages;
|
44 |
+
$response->setContent($data);
|
45 |
+
}
|
46 |
+
}
|
src/MWP/EventListener/FixCompatibility.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_FixCompatibility implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $context;
|
15 |
+
|
16 |
+
public function __construct(MWP_WordPress_Context $context)
|
17 |
+
{
|
18 |
+
$this->context = $context;
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getSubscribedEvents()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
MWP_Event_Events::ACTION_RESPONSE => 'fixWpSuperCache',
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function fixWpSuperCache()
|
29 |
+
{
|
30 |
+
if ($this->context->hasConstant('ADVANCEDCACHEPROBLEM') && $this->context->getConstant('ADVANCEDCACHEPROBLEM')) {
|
31 |
+
$this->context->set('wp_cache_config_file', null);
|
32 |
+
}
|
33 |
+
}
|
34 |
+
}
|
src/MWP/EventListener/MasterRequest/SetRequestSettings.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_MasterRequest_SetRequestSettings implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $context;
|
15 |
+
|
16 |
+
public function __construct(MWP_WordPress_Context $context)
|
17 |
+
{
|
18 |
+
$this->context = $context;
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getSubscribedEvents()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
MWP_Event_Events::MASTER_REQUEST => array('onMasterRequest', -1000),
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function onMasterRequest(MWP_Event_MasterRequest $event)
|
29 |
+
{
|
30 |
+
if (!$event->getRequest()->isAuthenticated()) {
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
$data = $event->getRequest()->getData();
|
34 |
+
|
35 |
+
$this->defineWpAdmin($data);
|
36 |
+
$this->defineWpAjax($data);
|
37 |
+
$this->setWpPage($data);
|
38 |
+
|
39 |
+
// Master should never get redirected by the worker, since it expects worker response.
|
40 |
+
$this->context->addFilter('wp_redirect', array($this, 'disableRedirect'));
|
41 |
+
}
|
42 |
+
|
43 |
+
private function defineWpAdmin(array $data)
|
44 |
+
{
|
45 |
+
if (empty($data['wpAdmin'])) {
|
46 |
+
return;
|
47 |
+
}
|
48 |
+
|
49 |
+
$this->context->setConstant('WP_ADMIN', true, false);
|
50 |
+
}
|
51 |
+
|
52 |
+
private function defineWpAjax(array $data)
|
53 |
+
{
|
54 |
+
if (empty($data['wpAjax'])) {
|
55 |
+
return;
|
56 |
+
}
|
57 |
+
|
58 |
+
$this->context->setConstant('DOING_AJAX', true, false);
|
59 |
+
}
|
60 |
+
|
61 |
+
private function setWpPage(array $data)
|
62 |
+
{
|
63 |
+
if (empty($data['wpPage'])) {
|
64 |
+
return;
|
65 |
+
}
|
66 |
+
|
67 |
+
$this->context->set('pagenow', $data['wpPage']);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @internal
|
72 |
+
*/
|
73 |
+
public function disableRedirect()
|
74 |
+
{
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
}
|
src/MWP/EventListener/MasterResponse/LogResponse.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_MasterResponse_LogResponse implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $logger;
|
15 |
+
|
16 |
+
public function __construct(Monolog_Logger $logger)
|
17 |
+
{
|
18 |
+
$this->logger = $logger;
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function getSubscribedEvents()
|
22 |
+
{
|
23 |
+
return array(
|
24 |
+
MWP_Event_Events::MASTER_RESPONSE => array('onMasterResponse'),
|
25 |
+
);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function onMasterResponse(MWP_Event_MasterResponse $event)
|
29 |
+
{
|
30 |
+
$response = $event->getResponse();
|
31 |
+
$content = $response->getContent();
|
32 |
+
|
33 |
+
$status = 'unknown';
|
34 |
+
|
35 |
+
if (is_array($content)) {
|
36 |
+
if (array_key_exists('success', $content)) {
|
37 |
+
$status = 'success';
|
38 |
+
} elseif (array_key_exists('error', $content)) {
|
39 |
+
$status = 'error';
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->logger->debug('Master response: {status}', array(
|
44 |
+
'status' => $status,
|
45 |
+
'content' => $content,
|
46 |
+
));
|
47 |
+
}
|
48 |
+
}
|
src/MWP/EventListener/PublicRequest/AddStatusPage.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_EventListener_PublicRequest_AddStatusPage implements Symfony_EventDispatcher_EventSubscriberInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
private $context;
|
15 |
+
|
16 |
+
private $configuration;
|
17 |
+
|
18 |
+
public function __construct(MWP_WordPress_Context $context, MWP_Worker_Configuration $configuration)
|
19 |
+
{
|
20 |
+
$this->context = $context;
|
21 |
+
$this->configuration = $configuration;
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function getSubscribedEvents()
|
25 |
+
{
|
26 |
+
return array(
|
27 |
+
MWP_Event_Events::PUBLIC_REQUEST => 'onPublicRequest',
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @internal
|
33 |
+
*/
|
34 |
+
public function onPublicRequest(MWP_Event_PublicRequest $event)
|
35 |
+
{
|
36 |
+
$this->context->addAction('admin_menu', array($this, 'addStatusPage'));
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @internal
|
41 |
+
*/
|
42 |
+
public function addStatusPage()
|
43 |
+
{
|
44 |
+
$this->context->addSubMenuPage(null, 'ManageWP Worker Status', 'ManageWP Worker Status', 'activate_plugins', 'worker-status', array($this, 'statusPage'));
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @internal
|
49 |
+
*/
|
50 |
+
public function statusPage()
|
51 |
+
{
|
52 |
+
$pluginFile = 'worker/init.php';
|
53 |
+
$deactivateUrl = $this->context->wpNonceUrl('plugins.php?action=deactivate&plugin='.$pluginFile, 'deactivate-plugin_'.$pluginFile);
|
54 |
+
|
55 |
+
$info = json_encode(array(
|
56 |
+
'wrksettings' => $this->context->optionGet('wrksettings'),
|
57 |
+
'connected' => (bool) $this->configuration->getPublicKey(),
|
58 |
+
'connectedLegacy' => (bool) $this->configuration->getSecureKey(),
|
59 |
+
));
|
60 |
+
?>
|
61 |
+
<div class="wrap">
|
62 |
+
<div id="icon-tools" class="icon32"></div>
|
63 |
+
<h2>ManageWP Worker Status</h2>
|
64 |
+
</div>
|
65 |
+
|
66 |
+
<p>
|
67 |
+
<a id="worker-status-deactivate" class="button" href="<?php echo $deactivateUrl ?>">Deactivate</a>
|
68 |
+
</p>
|
69 |
+
|
70 |
+
<textarea id="worker-status-settings" style="display: none;"><?php echo htmlspecialchars($info, ENT_QUOTES) ?></textarea>
|
71 |
+
<?php
|
72 |
+
}
|
73 |
+
}
|
src/MWP/EventListener/PublicRequest/AutomaticLogin.php
CHANGED
@@ -19,12 +19,15 @@ class MWP_EventListener_PublicRequest_AutomaticLogin implements Symfony_EventDis
|
|
19 |
|
20 |
private $configuration;
|
21 |
|
22 |
-
|
|
|
|
|
23 |
{
|
24 |
$this->context = $context;
|
25 |
$this->nonceManager = $nonceManager;
|
26 |
$this->signer = $signer;
|
27 |
$this->configuration = $configuration;
|
|
|
28 |
}
|
29 |
|
30 |
public static function getSubscribedEvents()
|
@@ -93,6 +96,7 @@ class MWP_EventListener_PublicRequest_AutomaticLogin implements Symfony_EventDis
|
|
93 |
}
|
94 |
|
95 |
$this->context->setCurrentUser($user);
|
|
|
96 |
$this->context->setAuthCookie($user);
|
97 |
|
98 |
$currentUri = empty($request->server['REQUEST_URI']) ? '/' : $request->server['REQUEST_URI'];
|
@@ -142,4 +146,31 @@ class MWP_EventListener_PublicRequest_AutomaticLogin implements Symfony_EventDis
|
|
142 |
// Replace everything from "?" onwards with "?key=value" or an empty string.
|
143 |
return substr($uri, 0, strpos($uri, '?')).(count($query) ? '?'.http_build_query($query) : '');
|
144 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
}
|
19 |
|
20 |
private $configuration;
|
21 |
|
22 |
+
private $sessionStore;
|
23 |
+
|
24 |
+
public function __construct(MWP_WordPress_Context $context, MWP_Security_NonceManager $nonceManager, MWP_Signer_Interface $signer, MWP_Worker_Configuration $configuration, MWP_WordPress_SessionStore $sessionStore)
|
25 |
{
|
26 |
$this->context = $context;
|
27 |
$this->nonceManager = $nonceManager;
|
28 |
$this->signer = $signer;
|
29 |
$this->configuration = $configuration;
|
30 |
+
$this->sessionStore = $sessionStore;
|
31 |
}
|
32 |
|
33 |
public static function getSubscribedEvents()
|
96 |
}
|
97 |
|
98 |
$this->context->setCurrentUser($user);
|
99 |
+
$this->attachSessionTokenListener();
|
100 |
$this->context->setAuthCookie($user);
|
101 |
|
102 |
$currentUri = empty($request->server['REQUEST_URI']) ? '/' : $request->server['REQUEST_URI'];
|
146 |
// Replace everything from "?" onwards with "?key=value" or an empty string.
|
147 |
return substr($uri, 0, strpos($uri, '?')).(count($query) ? '?'.http_build_query($query) : '');
|
148 |
}
|
149 |
+
|
150 |
+
private function attachSessionTokenListener()
|
151 |
+
{
|
152 |
+
if (!$this->context->getSessionTokens($this->context->getCurrentUser()->ID)) {
|
153 |
+
return;
|
154 |
+
}
|
155 |
+
|
156 |
+
$this->context->addAction('set_auth_cookie', array($this, 'storeSessionToken'), 10, 1);
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @param string $cookieValue
|
161 |
+
*
|
162 |
+
* @internal
|
163 |
+
*/
|
164 |
+
public function storeSessionToken($cookieValue)
|
165 |
+
{
|
166 |
+
$cookieElements = explode('|', $cookieValue);
|
167 |
+
|
168 |
+
if (empty($cookieElements[2])) {
|
169 |
+
return;
|
170 |
+
}
|
171 |
+
|
172 |
+
$token = $cookieElements[2];
|
173 |
+
|
174 |
+
$this->sessionStore->add($this->context->getCurrentUser()->ID, $token);
|
175 |
+
}
|
176 |
}
|
src/MWP/EventListener/PublicRequest/BrandContactSupport.php
CHANGED
@@ -15,6 +15,8 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
15 |
|
16 |
private $brand;
|
17 |
|
|
|
|
|
18 |
/**
|
19 |
* Required WordPress capability to access the page.
|
20 |
*
|
@@ -22,10 +24,11 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
22 |
*/
|
23 |
private $capability = 'read';
|
24 |
|
25 |
-
public function __construct(MWP_WordPress_Context $context, MWP_Worker_Brand $brand)
|
26 |
{
|
27 |
-
$this->context
|
28 |
-
$this->brand
|
|
|
29 |
}
|
30 |
|
31 |
public static function getSubscribedEvents()
|
@@ -35,7 +38,7 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
35 |
);
|
36 |
}
|
37 |
|
38 |
-
public function enableContactSupport(
|
39 |
{
|
40 |
if (!$this->brand->isActive()) {
|
41 |
return;
|
@@ -51,7 +54,7 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
51 |
$this->context->addAction('admin_head', array($this, 'printSupportScript'));
|
52 |
$this->context->addAction('admin_footer', array($this, 'printSupportDialog'));
|
53 |
|
54 |
-
$this->
|
55 |
}
|
56 |
|
57 |
/**
|
@@ -90,9 +93,9 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
90 |
?>
|
91 |
<script type="text/javascript">
|
92 |
jQuery(document).ready(function ($) {
|
93 |
-
var $dialog = $('#
|
94 |
-
var $form = $('#
|
95 |
-
var $messageContainer = $('#
|
96 |
$form.submit(function (e) {
|
97 |
e.preventDefault();
|
98 |
var data = $(this).serialize();
|
@@ -125,7 +128,7 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
125 |
title: 'Contact Support',
|
126 |
dialogClass: 'mwp-support-dialog',
|
127 |
close: function () {
|
128 |
-
$('#
|
129 |
$(this).dialog("destroy");
|
130 |
}
|
131 |
});
|
@@ -148,7 +151,7 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
148 |
|
149 |
ob_start();
|
150 |
?>
|
151 |
-
<div id="
|
152 |
<?php if (!empty($contactText)): ?>
|
153 |
<div>
|
154 |
<p><?php echo $contactText ?></p>
|
@@ -156,11 +159,11 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
156 |
<?php endif ?>
|
157 |
<?php if ($contactType == MWP_Worker_Brand::CONTACT_TYPE_TEXT_PLUS_FORM): ?>
|
158 |
<div style="margin: 19px 0 0;">
|
159 |
-
<form method="post" id="
|
160 |
-
<textarea name="support_mwp_message" id="
|
161 |
<button type="submit" class="button-primary" style="display:block;margin:20px auto 7px auto;border:1px solid #a1a1a1;padding:0 31px;border-radius: 4px;">Send</button>
|
162 |
</form>
|
163 |
-
<div id="
|
164 |
<style scoped="scoped">
|
165 |
.mwp-support-dialog.ui-dialog {
|
166 |
z-index: 300002;
|
@@ -175,14 +178,14 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
175 |
$this->context->output($content);
|
176 |
}
|
177 |
|
178 |
-
|
179 |
{
|
180 |
-
$request = $
|
181 |
if (!isset($request->request['support_mwp_message']) || !is_scalar($request->request['support_mwp_message'])) {
|
182 |
return;
|
183 |
}
|
184 |
|
185 |
-
if (
|
186 |
return;
|
187 |
}
|
188 |
|
@@ -195,13 +198,12 @@ class MWP_EventListener_PublicRequest_BrandContactSupport implements Symfony_Eve
|
|
195 |
|
196 |
if (empty($message)) {
|
197 |
// Message is set, but it's empty.
|
198 |
-
$
|
199 |
'success' => false,
|
200 |
'message' => "Please enter a message.",
|
201 |
-
))
|
202 |
-
$
|
203 |
-
|
204 |
-
return;
|
205 |
}
|
206 |
$subject = 'New ticket for site '.$this->context->getHomeUrl();
|
207 |
$message = <<<EOF
|
@@ -216,7 +218,8 @@ EOF;
|
|
216 |
'message' => $emailSent ? "Message successfully sent." : "Unable to send email. Please try again.",
|
217 |
);
|
218 |
|
219 |
-
$
|
220 |
-
$
|
|
|
221 |
}
|
222 |
}
|
15 |
|
16 |
private $brand;
|
17 |
|
18 |
+
private $requestStack;
|
19 |
+
|
20 |
/**
|
21 |
* Required WordPress capability to access the page.
|
22 |
*
|
24 |
*/
|
25 |
private $capability = 'read';
|
26 |
|
27 |
+
public function __construct(MWP_WordPress_Context $context, MWP_Worker_Brand $brand, MWP_Worker_RequestStack $requestStack)
|
28 |
{
|
29 |
+
$this->context = $context;
|
30 |
+
$this->brand = $brand;
|
31 |
+
$this->requestStack = $requestStack;
|
32 |
}
|
33 |
|
34 |
public static function getSubscribedEvents()
|
38 |
);
|
39 |
}
|
40 |
|
41 |
+
public function enableContactSupport()
|
42 |
{
|
43 |
if (!$this->brand->isActive()) {
|
44 |
return;
|
54 |
$this->context->addAction('admin_head', array($this, 'printSupportScript'));
|
55 |
$this->context->addAction('admin_footer', array($this, 'printSupportDialog'));
|
56 |
|
57 |
+
$this->context->addAction('init', array($this, 'handleSupportForm'));
|
58 |
}
|
59 |
|
60 |
/**
|
93 |
?>
|
94 |
<script type="text/javascript">
|
95 |
jQuery(document).ready(function ($) {
|
96 |
+
var $dialog = $('#mwp_support_dialog');
|
97 |
+
var $form = $('#mwp_support_form');
|
98 |
+
var $messageContainer = $('#mwp_support_response_id');
|
99 |
$form.submit(function (e) {
|
100 |
e.preventDefault();
|
101 |
var data = $(this).serialize();
|
128 |
title: 'Contact Support',
|
129 |
dialogClass: 'mwp-support-dialog',
|
130 |
close: function () {
|
131 |
+
$('#mwp_support_response_id').html('');
|
132 |
$(this).dialog("destroy");
|
133 |
}
|
134 |
});
|
151 |
|
152 |
ob_start();
|
153 |
?>
|
154 |
+
<div id="mwp_support_dialog" style="display: none;">
|
155 |
<?php if (!empty($contactText)): ?>
|
156 |
<div>
|
157 |
<p><?php echo $contactText ?></p>
|
159 |
<?php endif ?>
|
160 |
<?php if ($contactType == MWP_Worker_Brand::CONTACT_TYPE_TEXT_PLUS_FORM): ?>
|
161 |
<div style="margin: 19px 0 0;">
|
162 |
+
<form method="post" id="mwp_support_form">
|
163 |
+
<textarea name="support_mwp_message" id="mwp_support_message" style="width:500px;height:150px;display:block;margin-left:auto;margin-right:auto;"></textarea>
|
164 |
<button type="submit" class="button-primary" style="display:block;margin:20px auto 7px auto;border:1px solid #a1a1a1;padding:0 31px;border-radius: 4px;">Send</button>
|
165 |
</form>
|
166 |
+
<div id="mwp_support_response_id" style="margin-top: 14px"></div>
|
167 |
<style scoped="scoped">
|
168 |
.mwp-support-dialog.ui-dialog {
|
169 |
z-index: 300002;
|
178 |
$this->context->output($content);
|
179 |
}
|
180 |
|
181 |
+
public function handleSupportForm()
|
182 |
{
|
183 |
+
$request = $this->requestStack->getMasterRequest();
|
184 |
if (!isset($request->request['support_mwp_message']) || !is_scalar($request->request['support_mwp_message'])) {
|
185 |
return;
|
186 |
}
|
187 |
|
188 |
+
if (!$this->context->isGranted($this->capability)) {
|
189 |
return;
|
190 |
}
|
191 |
|
198 |
|
199 |
if (empty($message)) {
|
200 |
// Message is set, but it's empty.
|
201 |
+
$response = new MWP_Http_JsonResponse(array(
|
202 |
'success' => false,
|
203 |
'message' => "Please enter a message.",
|
204 |
+
));
|
205 |
+
$response->send();
|
206 |
+
exit;
|
|
|
207 |
}
|
208 |
$subject = 'New ticket for site '.$this->context->getHomeUrl();
|
209 |
$message = <<<EOF
|
218 |
'message' => $emailSent ? "Message successfully sent." : "Unable to send email. Please try again.",
|
219 |
);
|
220 |
|
221 |
+
$response = new MWP_Http_JsonResponse($status);
|
222 |
+
$response->send();
|
223 |
+
exit;
|
224 |
}
|
225 |
}
|
src/MWP/EventListener/PublicRequest/SetHitCounter.php
CHANGED
@@ -41,14 +41,16 @@ class MWP_EventListener_PublicRequest_SetHitCounter implements Symfony_EventDisp
|
|
41 |
/**
|
42 |
* @param MWP_WordPress_Context $context
|
43 |
* @param MWP_Extension_HitCounter $hitCounter
|
|
|
44 |
* @param string[] $blacklistedIps
|
45 |
* @param string[] $userAgentList
|
46 |
* @param bool $userAgentMatchingMethod
|
47 |
*/
|
48 |
-
public function __construct(MWP_WordPress_Context $context, MWP_Extension_HitCounter $hitCounter, array $blacklistedIps = array(), array $userAgentList = array(), $userAgentMatchingMethod = self::METHOD_BLACKLIST)
|
49 |
{
|
50 |
$this->context = $context;
|
51 |
$this->hitCounter = $hitCounter;
|
|
|
52 |
$this->blacklistedIps = $blacklistedIps;
|
53 |
$this->userAgentList = $userAgentList;
|
54 |
$this->userAgentMatchingMethod = $userAgentMatchingMethod;
|
@@ -60,13 +62,23 @@ class MWP_EventListener_PublicRequest_SetHitCounter implements Symfony_EventDisp
|
|
60 |
public static function getSubscribedEvents()
|
61 |
{
|
62 |
return array(
|
63 |
-
MWP_Event_Events::PUBLIC_REQUEST =>
|
64 |
);
|
65 |
}
|
66 |
|
67 |
public function onPublicRequest(MWP_Event_PublicRequest $event)
|
68 |
{
|
69 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
if ($this->context->isInAdminPanel()) {
|
72 |
return;
|
41 |
/**
|
42 |
* @param MWP_WordPress_Context $context
|
43 |
* @param MWP_Extension_HitCounter $hitCounter
|
44 |
+
* @param MWP_Worker_RequestStack $requestStack
|
45 |
* @param string[] $blacklistedIps
|
46 |
* @param string[] $userAgentList
|
47 |
* @param bool $userAgentMatchingMethod
|
48 |
*/
|
49 |
+
public function __construct(MWP_WordPress_Context $context, MWP_Extension_HitCounter $hitCounter, MWP_Worker_RequestStack $requestStack, array $blacklistedIps = array(), array $userAgentList = array(), $userAgentMatchingMethod = self::METHOD_BLACKLIST)
|
50 |
{
|
51 |
$this->context = $context;
|
52 |
$this->hitCounter = $hitCounter;
|
53 |
+
$this->requestStack = $requestStack;
|
54 |
$this->blacklistedIps = $blacklistedIps;
|
55 |
$this->userAgentList = $userAgentList;
|
56 |
$this->userAgentMatchingMethod = $userAgentMatchingMethod;
|
62 |
public static function getSubscribedEvents()
|
63 |
{
|
64 |
return array(
|
65 |
+
MWP_Event_Events::PUBLIC_REQUEST => 'onPublicRequest',
|
66 |
);
|
67 |
}
|
68 |
|
69 |
public function onPublicRequest(MWP_Event_PublicRequest $event)
|
70 |
{
|
71 |
+
$this->context->addAction('wp', array($this, 'countHit'));
|
72 |
+
}
|
73 |
+
|
74 |
+
public function countHit()
|
75 |
+
{
|
76 |
+
$request = $this->requestStack->getMasterRequest();
|
77 |
+
|
78 |
+
if (!$this->context->hasConstant('WP_USE_THEMES') || !$this->context->getConstant('WP_USE_THEMES')) {
|
79 |
+
// The file is not visited via "index.php".
|
80 |
+
return;
|
81 |
+
}
|
82 |
|
83 |
if ($this->context->isInAdminPanel()) {
|
84 |
return;
|
src/MWP/EventListener/PublicRequest/SetPluginInfo.php
CHANGED
@@ -39,6 +39,20 @@ class MWP_EventListener_PublicRequest_SetPluginInfo implements Symfony_EventDisp
|
|
39 |
// This is a horrible hack, but it will allow us to hide a MU plugin in rebranded installations.
|
40 |
$this->context->addFilter('show_advanced_plugins', array($this, 'muPluginListFilter'), 10, 2);
|
41 |
$this->context->addFilter('plugin_row_meta', array($this, 'hidePluginDetails'), 10, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
|
44 |
/**
|
@@ -94,7 +108,7 @@ class MWP_EventListener_PublicRequest_SetPluginInfo implements Symfony_EventDisp
|
|
94 |
*/
|
95 |
public function muPluginListFilter($previousValue, $type)
|
96 |
{
|
97 |
-
if (!$this->brand->isActive()
|
98 |
return $previousValue;
|
99 |
}
|
100 |
|
@@ -113,7 +127,17 @@ class MWP_EventListener_PublicRequest_SetPluginInfo implements Symfony_EventDisp
|
|
113 |
return $previousValue;
|
114 |
}
|
115 |
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
return $previousValue;
|
119 |
}
|
39 |
// This is a horrible hack, but it will allow us to hide a MU plugin in rebranded installations.
|
40 |
$this->context->addFilter('show_advanced_plugins', array($this, 'muPluginListFilter'), 10, 2);
|
41 |
$this->context->addFilter('plugin_row_meta', array($this, 'hidePluginDetails'), 10, 2);
|
42 |
+
$this->context->addFilter('site_transient_update_plugins', array($this, 'parseUpdatePlugins'));
|
43 |
+
}
|
44 |
+
|
45 |
+
public function parseUpdatePlugins($updates)
|
46 |
+
{
|
47 |
+
if (!$this->brand->isActive()) {
|
48 |
+
return $updates;
|
49 |
+
}
|
50 |
+
|
51 |
+
if (isset($updates->response[$this->slug])) {
|
52 |
+
unset($updates->response[$this->slug]);
|
53 |
+
}
|
54 |
+
|
55 |
+
return $updates;
|
56 |
}
|
57 |
|
58 |
/**
|
108 |
*/
|
109 |
public function muPluginListFilter($previousValue, $type)
|
110 |
{
|
111 |
+
if (!$this->brand->isActive()) {
|
112 |
return $previousValue;
|
113 |
}
|
114 |
|
127 |
return $previousValue;
|
128 |
}
|
129 |
|
130 |
+
if ($this->brand->isHide()) {
|
131 |
+
unset($plugins['mustuse'][$this->loaderName]);
|
132 |
+
} else {
|
133 |
+
$plugins['mustuse'][$this->loaderName]['Name'] = $this->brand->getName();
|
134 |
+
$plugins['mustuse'][$this->loaderName]['Title'] = $this->brand->getName();
|
135 |
+
$plugins['mustuse'][$this->loaderName]['Description'] = $this->brand->getDescription();
|
136 |
+
$plugins['mustuse'][$this->loaderName]['AuthorURI'] = $this->brand->getAuthorUrl();
|
137 |
+
$plugins['mustuse'][$this->loaderName]['Author'] = $this->brand->getAuthor();
|
138 |
+
$plugins['mustuse'][$this->loaderName]['AuthorName'] = $this->brand->getAuthor();
|
139 |
+
$plugins['mustuse'][$this->loaderName]['PluginURI'] = '';
|
140 |
+
}
|
141 |
|
142 |
return $previousValue;
|
143 |
}
|
src/MWP/Http/JsonResponse.php
CHANGED
@@ -10,10 +10,10 @@
|
|
10 |
|
11 |
class MWP_Http_JsonResponse extends MWP_Http_Response
|
12 |
{
|
13 |
-
public function __construct($content, $headers = array())
|
14 |
{
|
15 |
$headers['content-type'] = 'application/json';
|
16 |
-
parent::__construct($content, $headers);
|
17 |
}
|
18 |
|
19 |
public function getContentAsString()
|
10 |
|
11 |
class MWP_Http_JsonResponse extends MWP_Http_Response
|
12 |
{
|
13 |
+
public function __construct($content, $statusCode = 200, array $headers = array())
|
14 |
{
|
15 |
$headers['content-type'] = 'application/json';
|
16 |
+
parent::__construct($content, $statusCode, $headers);
|
17 |
}
|
18 |
|
19 |
public function getContentAsString()
|
src/MWP/Http/MultipartResponse.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Constructs a Multipart response into string or stream.
|
13 |
+
*/
|
14 |
+
class MWP_Http_MultipartResponse extends MWP_Http_Response implements MWP_Http_StreamingResponseInterface
|
15 |
+
{
|
16 |
+
|
17 |
+
/** @var string Multipart boundary */
|
18 |
+
private $boundary = '';
|
19 |
+
|
20 |
+
public function __construct($parts, $boundary = null, $statusCode = 200, array $headers = array())
|
21 |
+
{
|
22 |
+
if ($boundary === null) {
|
23 |
+
$boundary = uniqid();
|
24 |
+
}
|
25 |
+
|
26 |
+
$this->boundary = $boundary;
|
27 |
+
$headers["content-type"] = "multipart/mixed; boundary=".$this->boundary;
|
28 |
+
|
29 |
+
if (!isset($headers["content-transfer-encoding"])) {
|
30 |
+
$headers["content-transfer-encoding"] = "binary";
|
31 |
+
}
|
32 |
+
|
33 |
+
parent::__construct($parts, $statusCode, $headers);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* {@inheritdoc}
|
38 |
+
*/
|
39 |
+
public function getContentAsString()
|
40 |
+
{
|
41 |
+
/** @var MWP_Http_MultipartResponsePart[] $parts */
|
42 |
+
$parts = $this->content;
|
43 |
+
|
44 |
+
// Multipart header
|
45 |
+
$output = "\r\n".$this->getMultipartBoundary()."\r\n";
|
46 |
+
|
47 |
+
foreach ($parts as $part) {
|
48 |
+
$output .= $this->createPartResponse($part).$this->getMultipartBoundary();
|
49 |
+
}
|
50 |
+
|
51 |
+
// End multipart boundary
|
52 |
+
$output .= '--';
|
53 |
+
|
54 |
+
return $output;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @return MWP_Stream_Interface
|
59 |
+
*/
|
60 |
+
public function createResponseStream()
|
61 |
+
{
|
62 |
+
/** @var MWP_Http_MultipartResponsePart[] $parts */
|
63 |
+
$parts = $this->content;
|
64 |
+
$stream = new MWP_Stream_Append();
|
65 |
+
|
66 |
+
$stream->addStream(MWP_Stream_Stream::factory("\r\n".$this->getMultipartBoundary()));
|
67 |
+
|
68 |
+
foreach ($parts as $part) {
|
69 |
+
$stream->addStream(MWP_Stream_Stream::factory("\r\n"));
|
70 |
+
$stream->addStream($this->createPartStream($part));
|
71 |
+
$stream->addStream(MWP_Stream_Stream::factory("\r\n".$this->getMultipartBoundary()));
|
72 |
+
}
|
73 |
+
|
74 |
+
$stream->addStream(MWP_Stream_Stream::factory("--"));
|
75 |
+
|
76 |
+
return $stream;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @return string
|
81 |
+
*/
|
82 |
+
public function getBoundary()
|
83 |
+
{
|
84 |
+
return $this->boundary;
|
85 |
+
}
|
86 |
+
|
87 |
+
private function createPartResponse(MWP_Http_MultipartResponsePart $part)
|
88 |
+
{
|
89 |
+
$response = '';
|
90 |
+
|
91 |
+
foreach ($part->getHeaders() as $header => $value) {
|
92 |
+
if (strcasecmp("content-location", $header) === 0) {
|
93 |
+
// Content-Location can contain special characters (like \r\n for example)
|
94 |
+
$value = urlencode($value);
|
95 |
+
}
|
96 |
+
$response .= sprintf("%s: %s\r\n", strtolower($header), $value);
|
97 |
+
}
|
98 |
+
|
99 |
+
$response .= sprintf("\r\n%s\r\n", (string) $part->getBody());
|
100 |
+
|
101 |
+
return $response;
|
102 |
+
}
|
103 |
+
|
104 |
+
private function createPartStream(MWP_Http_MultipartResponsePart $part)
|
105 |
+
{
|
106 |
+
$stream = new MWP_Stream_Append();
|
107 |
+
|
108 |
+
foreach ($part->getHeaders() as $header => $value) {
|
109 |
+
if (strcasecmp("content-location", $header) === 0) {
|
110 |
+
// Content-Location can contain special characters (like \r\n for example)
|
111 |
+
$value = urlencode($value);
|
112 |
+
}
|
113 |
+
$stream->addStream(MWP_Stream_Stream::factory(sprintf("%s: %s\r\n", strtolower($header), $value)));
|
114 |
+
}
|
115 |
+
|
116 |
+
$stream->addStream(MWP_Stream_Stream::factory("\r\n"));
|
117 |
+
$stream->addStream($part->getBody());
|
118 |
+
|
119 |
+
return $stream;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
private function getMultipartBoundary()
|
126 |
+
{
|
127 |
+
return sprintf("--%s", $this->boundary);
|
128 |
+
}
|
129 |
+
}
|
src/MWP/Http/MultipartResponsePart.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Http_MultipartResponsePart
|
12 |
+
{
|
13 |
+
|
14 |
+
/** @var array */
|
15 |
+
private $headers = array();
|
16 |
+
|
17 |
+
/** @var MWP_Stream_Interface */
|
18 |
+
private $body;
|
19 |
+
|
20 |
+
function __construct($headers, $body = null)
|
21 |
+
{
|
22 |
+
$this->headers = array_change_key_case($headers, CASE_LOWER);
|
23 |
+
$this->setBody($body);
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @param string $header
|
28 |
+
* @param string $value
|
29 |
+
*/
|
30 |
+
public function setHeader($header, $value)
|
31 |
+
{
|
32 |
+
$this->headers[strtolower($header)] = $value;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @param $header
|
37 |
+
*
|
38 |
+
* @return string|null
|
39 |
+
*/
|
40 |
+
public function getHeader($header)
|
41 |
+
{
|
42 |
+
if ($this->hasHeader($header)) {
|
43 |
+
return $this->headers[strtolower($header)];
|
44 |
+
}
|
45 |
+
|
46 |
+
return null;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param string $header
|
51 |
+
*
|
52 |
+
* @return bool
|
53 |
+
*/
|
54 |
+
public function hasHeader($header)
|
55 |
+
{
|
56 |
+
return isset($this->headers[strtolower($header)]);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @return array
|
61 |
+
*/
|
62 |
+
public function getHeaders()
|
63 |
+
{
|
64 |
+
return $this->headers;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @return MWP_Stream_Interface|null
|
69 |
+
*/
|
70 |
+
public function getBody()
|
71 |
+
{
|
72 |
+
return $this->body;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @param MWP_Stream_Interface $body
|
77 |
+
*/
|
78 |
+
public function setBody($body)
|
79 |
+
{
|
80 |
+
if ($body !== null && !$body instanceof MWP_Stream_Interface) {
|
81 |
+
$body = MWP_Stream_Stream::factory($body);
|
82 |
+
}
|
83 |
+
|
84 |
+
$this->body = $body;
|
85 |
+
}
|
86 |
+
}
|
src/MWP/Http/RedirectResponse.php
CHANGED
@@ -10,10 +10,10 @@
|
|
10 |
|
11 |
class MWP_Http_RedirectResponse extends MWP_Http_Response
|
12 |
{
|
13 |
-
public function __construct($url, $
|
14 |
{
|
15 |
$headers['location'] = $url;
|
16 |
-
parent::__construct($url, $headers);
|
17 |
}
|
18 |
|
19 |
public function getContentAsString()
|
10 |
|
11 |
class MWP_Http_RedirectResponse extends MWP_Http_Response
|
12 |
{
|
13 |
+
public function __construct($url, $statusCode = 302, array $headers = array())
|
14 |
{
|
15 |
$headers['location'] = $url;
|
16 |
+
parent::__construct($url, $statusCode, $headers);
|
17 |
}
|
18 |
|
19 |
public function getContentAsString()
|
src/MWP/Http/Response.php
CHANGED
@@ -11,14 +11,91 @@
|
|
11 |
class MWP_Http_Response implements MWP_Http_ResponseInterface
|
12 |
{
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
protected $content;
|
15 |
|
|
|
|
|
16 |
protected $headers = array();
|
17 |
|
18 |
-
public function __construct($content, $headers = array())
|
19 |
{
|
20 |
-
$this->content
|
21 |
-
$this->
|
|
|
22 |
}
|
23 |
|
24 |
public function getContentAsString()
|
@@ -50,7 +127,23 @@ class MWP_Http_Response implements MWP_Http_ResponseInterface
|
|
50 |
public function send()
|
51 |
{
|
52 |
$this->sendHeaders();
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
|
56 |
protected function sendHeaders()
|
@@ -59,8 +152,17 @@ class MWP_Http_Response implements MWP_Http_ResponseInterface
|
|
59 |
return;
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
foreach ($this->headers as $headerName => $headerValue) {
|
63 |
-
header(sprintf('%s: %s', $headerName, $headerValue),
|
64 |
}
|
65 |
}
|
66 |
}
|
11 |
class MWP_Http_Response implements MWP_Http_ResponseInterface
|
12 |
{
|
13 |
|
14 |
+
/**
|
15 |
+
* Status codes translation table.
|
16 |
+
*
|
17 |
+
* The list of codes is complete according to the
|
18 |
+
* {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry}
|
19 |
+
* (last updated 2012-02-13).
|
20 |
+
*
|
21 |
+
* Unless otherwise noted, the status code is defined in RFC2616.
|
22 |
+
*
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
public static $statusTexts = array(
|
26 |
+
100 => 'Continue',
|
27 |
+
101 => 'Switching Protocols',
|
28 |
+
102 => 'Processing', // RFC2518
|
29 |
+
200 => 'OK',
|
30 |
+
201 => 'Created',
|
31 |
+
202 => 'Accepted',
|
32 |
+
203 => 'Non-Authoritative Information',
|
33 |
+
204 => 'No Content',
|
34 |
+
205 => 'Reset Content',
|
35 |
+
206 => 'Partial Content',
|
36 |
+
207 => 'Multi-Status', // RFC4918
|
37 |
+
208 => 'Already Reported', // RFC5842
|
38 |
+
226 => 'IM Used', // RFC3229
|
39 |
+
300 => 'Multiple Choices',
|
40 |
+
301 => 'Moved Permanently',
|
41 |
+
302 => 'Found',
|
42 |
+
303 => 'See Other',
|
43 |
+
304 => 'Not Modified',
|
44 |
+
305 => 'Use Proxy',
|
45 |
+
306 => 'Reserved',
|
46 |
+
307 => 'Temporary Redirect',
|
47 |
+
308 => 'Permanent Redirect', // RFC7238
|
48 |
+
400 => 'Bad Request',
|
49 |
+
401 => 'Unauthorized',
|
50 |
+
402 => 'Payment Required',
|
51 |
+
403 => 'Forbidden',
|
52 |
+
404 => 'Not Found',
|
53 |
+
405 => 'Method Not Allowed',
|
54 |
+
406 => 'Not Acceptable',
|
55 |
+
407 => 'Proxy Authentication Required',
|
56 |
+
408 => 'Request Timeout',
|
57 |
+
409 => 'Conflict',
|
58 |
+
410 => 'Gone',
|
59 |
+
411 => 'Length Required',
|
60 |
+
412 => 'Precondition Failed',
|
61 |
+
413 => 'Request Entity Too Large',
|
62 |
+
414 => 'Request-URI Too Long',
|
63 |
+
415 => 'Unsupported Media Type',
|
64 |
+
416 => 'Requested Range Not Satisfiable',
|
65 |
+
417 => 'Expectation Failed',
|
66 |
+
418 => 'I\'m a teapot', // RFC2324
|
67 |
+
422 => 'Unprocessable Entity', // RFC4918
|
68 |
+
423 => 'Locked', // RFC4918
|
69 |
+
424 => 'Failed Dependency', // RFC4918
|
70 |
+
425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817
|
71 |
+
426 => 'Upgrade Required', // RFC2817
|
72 |
+
428 => 'Precondition Required', // RFC6585
|
73 |
+
429 => 'Too Many Requests', // RFC6585
|
74 |
+
431 => 'Request Header Fields Too Large', // RFC6585
|
75 |
+
500 => 'Internal Server Error',
|
76 |
+
501 => 'Not Implemented',
|
77 |
+
502 => 'Bad Gateway',
|
78 |
+
503 => 'Service Unavailable',
|
79 |
+
504 => 'Gateway Timeout',
|
80 |
+
505 => 'HTTP Version Not Supported',
|
81 |
+
506 => 'Variant Also Negotiates (Experimental)', // RFC2295
|
82 |
+
507 => 'Insufficient Storage', // RFC4918
|
83 |
+
508 => 'Loop Detected', // RFC5842
|
84 |
+
510 => 'Not Extended', // RFC2774
|
85 |
+
511 => 'Network Authentication Required', // RFC6585
|
86 |
+
);
|
87 |
+
|
88 |
protected $content;
|
89 |
|
90 |
+
protected $statusCode;
|
91 |
+
|
92 |
protected $headers = array();
|
93 |
|
94 |
+
public function __construct($content, $statusCode = 200, array $headers = array())
|
95 |
{
|
96 |
+
$this->content = $content;
|
97 |
+
$this->statusCode = $statusCode;
|
98 |
+
$this->headers = array_change_key_case($headers, CASE_LOWER);
|
99 |
}
|
100 |
|
101 |
public function getContentAsString()
|
127 |
public function send()
|
128 |
{
|
129 |
$this->sendHeaders();
|
130 |
+
|
131 |
+
// Some plugins leave open buffers and when it happens the returned output is blank
|
132 |
+
$bufferCount = count(ob_list_handlers());
|
133 |
+
while ($bufferCount) {
|
134 |
+
ob_end_clean();
|
135 |
+
--$bufferCount;
|
136 |
+
}
|
137 |
+
|
138 |
+
if ($this instanceof MWP_Http_StreamingResponseInterface) {
|
139 |
+
$stream = $this->createResponseStream();
|
140 |
+
|
141 |
+
while (!$stream->eof()) {
|
142 |
+
print $stream->read(1048576);
|
143 |
+
}
|
144 |
+
} else {
|
145 |
+
print $this->getContentAsString();
|
146 |
+
}
|
147 |
}
|
148 |
|
149 |
protected function sendHeaders()
|
152 |
return;
|
153 |
}
|
154 |
|
155 |
+
$protocol = 'HTTP/1.1';
|
156 |
+
if (isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.0') {
|
157 |
+
$protocol = 'HTTP/1.0';
|
158 |
+
}
|
159 |
+
|
160 |
+
if (isset(self::$statusTexts[$this->statusCode])) {
|
161 |
+
header(sprintf('%s %s %s', $protocol, $this->statusCode, self::$statusTexts[$this->statusCode]), true, $this->statusCode);
|
162 |
+
}
|
163 |
+
|
164 |
foreach ($this->headers as $headerName => $headerValue) {
|
165 |
+
header(sprintf('%s: %s', $headerName, $headerValue), false, $this->statusCode);
|
166 |
}
|
167 |
}
|
168 |
}
|
src/MWP/Http/StreamingResponseInterface.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
interface MWP_Http_StreamingResponseInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @return MWP_Stream_Interface
|
15 |
+
*/
|
16 |
+
public function createResponseStream();
|
17 |
+
}
|
src/MWP/IncrementalBackup/Database/Configuration.php
ADDED
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_Configuration
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
private $username;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
private $password;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
private $database;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var bool
|
31 |
+
*/
|
32 |
+
private $socket;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string|null
|
36 |
+
*/
|
37 |
+
private $host;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var string|null
|
41 |
+
*/
|
42 |
+
private $socketPath;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @var string
|
46 |
+
*/
|
47 |
+
private $charset = 'utf8';
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @var int
|
51 |
+
*/
|
52 |
+
private $port;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param array $parameters
|
56 |
+
*/
|
57 |
+
public function __construct(array $parameters = array())
|
58 |
+
{
|
59 |
+
if (isset($parameters['username'])) {
|
60 |
+
$this->username = $parameters['username'];
|
61 |
+
}
|
62 |
+
|
63 |
+
if (isset($parameters['password'])) {
|
64 |
+
$this->password = $parameters['password'];
|
65 |
+
}
|
66 |
+
|
67 |
+
if (isset($parameters['socket'])) {
|
68 |
+
$this->socket = true;
|
69 |
+
$this->socketPath = $parameters['socket'];
|
70 |
+
} elseif (isset($parameters['host'])) {
|
71 |
+
$this->socket = false;
|
72 |
+
$this->host = $parameters['host'];
|
73 |
+
}
|
74 |
+
|
75 |
+
if (isset($parameters['port'])) {
|
76 |
+
$this->port = $parameters['port'];
|
77 |
+
}
|
78 |
+
|
79 |
+
if (isset($parameters['database'])) {
|
80 |
+
$this->database = $parameters['database'];
|
81 |
+
}
|
82 |
+
|
83 |
+
if (isset($parameters['charset'])) {
|
84 |
+
$this->charset = $parameters['charset'];
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @return string|null
|
90 |
+
*/
|
91 |
+
public function getHost()
|
92 |
+
{
|
93 |
+
return $this->host;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @return string|null
|
98 |
+
*/
|
99 |
+
public function getSocketPath()
|
100 |
+
{
|
101 |
+
return $this->socketPath;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return int
|
106 |
+
*/
|
107 |
+
public function getPort()
|
108 |
+
{
|
109 |
+
return $this->port;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @return boolean
|
114 |
+
*/
|
115 |
+
public function isSocket()
|
116 |
+
{
|
117 |
+
return $this->socket;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @return string
|
122 |
+
*/
|
123 |
+
public function getUsername()
|
124 |
+
{
|
125 |
+
return $this->username;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
public function getPassword()
|
132 |
+
{
|
133 |
+
return $this->password;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* @return string
|
138 |
+
*/
|
139 |
+
public function getDatabase()
|
140 |
+
{
|
141 |
+
return $this->database;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* @return string
|
146 |
+
*/
|
147 |
+
public function getCharset()
|
148 |
+
{
|
149 |
+
return $this->charset;
|
150 |
+
}
|
151 |
+
|
152 |
+
public static function createFromWordPressContext(MWP_WordPress_Context $context)
|
153 |
+
{
|
154 |
+
return self::createFromArray(array(
|
155 |
+
'username' => $context->getConstant('DB_USER'),
|
156 |
+
'password' => $context->getConstant('DB_PASSWORD'),
|
157 |
+
'database' => $context->getConstant('DB_NAME'),
|
158 |
+
'host' => $context->getConstant('DB_HOST'),
|
159 |
+
'charset' => $context->hasConstant('DB_CHARSET') ? $context->getConstant('DB_CHARSET') : 'utf8',
|
160 |
+
));
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* $parameters array should contain:
|
165 |
+
* - username: mysql username
|
166 |
+
* - password: mysql password
|
167 |
+
* - database: database name
|
168 |
+
* - host: host - can contain port or be a mysql socket
|
169 |
+
*/
|
170 |
+
public static function createFromArray(array $parameters = array())
|
171 |
+
{
|
172 |
+
$configuration = array(
|
173 |
+
'username' => isset($parameters['username']) ? $parameters['username'] : null,
|
174 |
+
'password' => isset($parameters['password']) ? $parameters['password'] : null,
|
175 |
+
'database' => $parameters['database'],
|
176 |
+
);
|
177 |
+
|
178 |
+
$databaseHost = $parameters['host'];
|
179 |
+
|
180 |
+
$port = 0;
|
181 |
+
$host = $databaseHost;
|
182 |
+
|
183 |
+
// Handle localhost:3306 cases
|
184 |
+
if (strpos($databaseHost, ':') !== false) {
|
185 |
+
list($host, $port) = explode(':', $databaseHost);
|
186 |
+
$port = (int) $port;
|
187 |
+
}
|
188 |
+
|
189 |
+
// Database host can be a path to mysql socket
|
190 |
+
if (strpos($databaseHost, '/') !== false || strpos($databaseHost, '\\') !== false) {
|
191 |
+
$socket = end(explode(':', $databaseHost));
|
192 |
+
|
193 |
+
$configuration['socket'] = $socket;
|
194 |
+
} else {
|
195 |
+
$configuration['host'] = $host;
|
196 |
+
if (!empty($port)) {
|
197 |
+
$configuration['port'] = $port;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
if (isset($parameters['charset'])) {
|
202 |
+
$configuration['charset'] = $parameters['charset'];
|
203 |
+
}
|
204 |
+
|
205 |
+
return new MWP_IncrementalBackup_Database_Configuration($configuration);
|
206 |
+
}
|
207 |
+
}
|
src/MWP/IncrementalBackup/Database/ConnectionInterface.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
interface MWP_IncrementalBackup_Database_ConnectionInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @param string $query
|
15 |
+
*
|
16 |
+
* @return MWP_IncrementalBackup_Database_StatementInterface
|
17 |
+
*/
|
18 |
+
public function query($query);
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param mixed $value any primitive value
|
22 |
+
*
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
+
public function quote($value);
|
26 |
+
}
|
src/MWP/IncrementalBackup/Database/DumpOptions.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_DumpOptions
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string[]
|
16 |
+
*/
|
17 |
+
private $tables = null;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var bool
|
21 |
+
*/
|
22 |
+
private $skipLockTables = true;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var bool
|
26 |
+
*/
|
27 |
+
private $dropTables = true;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return array
|
31 |
+
*/
|
32 |
+
public function getTables()
|
33 |
+
{
|
34 |
+
return $this->tables;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param array $tables
|
39 |
+
*/
|
40 |
+
public function setTables($tables)
|
41 |
+
{
|
42 |
+
$this->tables = $tables;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return boolean
|
47 |
+
*/
|
48 |
+
public function isSkipLockTables()
|
49 |
+
{
|
50 |
+
return $this->skipLockTables;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @param boolean $skipLockTables
|
55 |
+
*/
|
56 |
+
public function setSkipLockTables($skipLockTables)
|
57 |
+
{
|
58 |
+
$this->skipLockTables = $skipLockTables;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @return boolean
|
63 |
+
*/
|
64 |
+
public function isDropTables()
|
65 |
+
{
|
66 |
+
return $this->dropTables;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @param boolean $dropTables
|
71 |
+
*/
|
72 |
+
public function setDropTables($dropTables)
|
73 |
+
{
|
74 |
+
$this->dropTables = $dropTables;
|
75 |
+
}
|
76 |
+
|
77 |
+
public static function createFromArray(array $options = array())
|
78 |
+
{
|
79 |
+
$dumpOptions = new self();
|
80 |
+
|
81 |
+
if (isset($options['skip_lock_tables'])) {
|
82 |
+
$dumpOptions->setSkipLockTables($options['skip_lock_tables']);
|
83 |
+
}
|
84 |
+
|
85 |
+
return $dumpOptions;
|
86 |
+
}
|
87 |
+
}
|
src/MWP/IncrementalBackup/Database/DumperInterface.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
interface MWP_IncrementalBackup_Database_DumperInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @param array $tables Table names
|
15 |
+
*
|
16 |
+
* @return MWP_Stream_Interface
|
17 |
+
*/
|
18 |
+
function dump(array $tables);
|
19 |
+
}
|
src/MWP/IncrementalBackup/Database/Exception.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_Exception extends Exception
|
12 |
+
{
|
13 |
+
}
|
src/MWP/IncrementalBackup/Database/Exception/ConnectionException.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_Exception_ConnectionException extends MWP_IncrementalBackup_Database_Exception
|
12 |
+
{
|
13 |
+
}
|
src/MWP/IncrementalBackup/Database/MysqlConnection.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_MysqlConnection implements MWP_IncrementalBackup_Database_ConnectionInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var resource
|
16 |
+
*/
|
17 |
+
private $connection;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var
|
21 |
+
*/
|
22 |
+
private $configuration;
|
23 |
+
|
24 |
+
public function __construct(MWP_IncrementalBackup_Database_Configuration $configuration)
|
25 |
+
{
|
26 |
+
$this->configuration = $configuration;
|
27 |
+
|
28 |
+
if (!extension_loaded('mysql')) {
|
29 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException("Mysql extension is not loaded.");
|
30 |
+
}
|
31 |
+
|
32 |
+
if ($configuration->isSocket()) {
|
33 |
+
$this->connection = @mysql_connect(':'.$configuration->getSocketPath(), $configuration->getUsername(), $configuration->getPassword());
|
34 |
+
} else {
|
35 |
+
$host = $configuration->getHost();
|
36 |
+
if ($configuration->getPort() !== null) {
|
37 |
+
$host .= ':'.$configuration->getPort();
|
38 |
+
}
|
39 |
+
$this->connection = @mysql_connect($host, $configuration->getUsername(), $configuration->getPassword());
|
40 |
+
}
|
41 |
+
|
42 |
+
if (!is_resource($this->connection)) {
|
43 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException(mysql_error(), mysql_errno());
|
44 |
+
}
|
45 |
+
|
46 |
+
@mysql_set_charset($configuration->getCharset(), $this->connection);
|
47 |
+
mysql_select_db($configuration->getDatabase(), $this->connection);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @param string $query
|
52 |
+
*
|
53 |
+
* @throws MWP_IncrementalBackup_Database_Exception_ConnectionException
|
54 |
+
*
|
55 |
+
* @return MWP_IncrementalBackup_Database_StatementInterface
|
56 |
+
*/
|
57 |
+
public function query($query)
|
58 |
+
{
|
59 |
+
$result = mysql_query($query, $this->connection);
|
60 |
+
|
61 |
+
if ($result === false) {
|
62 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException(mysql_error($this->connection), mysql_errno($this->connection));
|
63 |
+
}
|
64 |
+
|
65 |
+
return new MWP_IncrementalBackup_Database_MysqlStatement($result);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @param mixed $value any primitive value
|
70 |
+
*
|
71 |
+
* @return string
|
72 |
+
*/
|
73 |
+
public function quote($value)
|
74 |
+
{
|
75 |
+
return mysql_real_escape_string($value, $this->connection);
|
76 |
+
}
|
77 |
+
}
|
src/MWP/IncrementalBackup/Database/MysqlDumpDumper.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_MysqlDumpDumper implements MWP_IncrementalBackup_Database_DumperInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Database_Configuration
|
16 |
+
*/
|
17 |
+
private $configuration;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var MWP_IncrementalBackup_Database_DumpOptions
|
21 |
+
*/
|
22 |
+
private $options;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param MWP_IncrementalBackup_Database_Configuration $configuration
|
26 |
+
* @param MWP_IncrementalBackup_Database_DumpOptions $options
|
27 |
+
*/
|
28 |
+
public function __construct(MWP_IncrementalBackup_Database_Configuration $configuration, MWP_IncrementalBackup_Database_DumpOptions $options)
|
29 |
+
{
|
30 |
+
$this->configuration = $configuration;
|
31 |
+
$this->options = $options;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* {@inheritdoc}
|
36 |
+
*/
|
37 |
+
function dump(array $tables = array())
|
38 |
+
{
|
39 |
+
if (!mwp_is_shell_available()) {
|
40 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::SHELL_NOT_AVAILABLE, 'Shell not available.');
|
41 |
+
}
|
42 |
+
|
43 |
+
$mysqldump = mwp_container()->getExecutableFinder()->find('mysqldump', 'mysqldump');
|
44 |
+
|
45 |
+
$processBuilder = Symfony_Process_ProcessBuilder::create()
|
46 |
+
->setWorkingDirectory(untrailingslashit(ABSPATH))
|
47 |
+
->setTimeout(3600)
|
48 |
+
->setPrefix($mysqldump)
|
49 |
+
// Continue even if we get an SQL error.
|
50 |
+
->add('--force')
|
51 |
+
// User for login if not current user.
|
52 |
+
->add('--user='.$this->configuration->getUsername())
|
53 |
+
// Password to use when connecting to server. If password is not given it's solicited on the tty.
|
54 |
+
->add('--password='.$this->configuration->getPassword())
|
55 |
+
// Add a DROP TABLE before each create.
|
56 |
+
->add('--add-drop-table');
|
57 |
+
|
58 |
+
if ($this->options->isSkipLockTables()) {
|
59 |
+
// Don't lock all tables for read.
|
60 |
+
$processBuilder->add('--lock-tables=false');
|
61 |
+
}
|
62 |
+
|
63 |
+
$processBuilder->add($this->configuration->getDatabase());
|
64 |
+
|
65 |
+
// Dump only specific tables
|
66 |
+
foreach ($tables as $table) {
|
67 |
+
$processBuilder->add($table);
|
68 |
+
}
|
69 |
+
|
70 |
+
if ($this->configuration->isSocket()) {
|
71 |
+
$processBuilder->add('--socket='.$this->configuration->getSocketPath());
|
72 |
+
} else {
|
73 |
+
$processBuilder->add('--host='.$this->configuration->getHost());
|
74 |
+
if (($port = $this->configuration->getPort()) !== null) {
|
75 |
+
$processBuilder->add('--port='.$port);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
$process = $processBuilder->getProcess();
|
80 |
+
|
81 |
+
mwp_logger()->info('Database dumping process starting', array(
|
82 |
+
'executable_location' => $mysqldump,
|
83 |
+
'command_line' => $process->getCommandLine(),
|
84 |
+
));
|
85 |
+
|
86 |
+
return new MWP_Stream_ProcessOutput($process);
|
87 |
+
}
|
88 |
+
}
|
src/MWP/IncrementalBackup/Database/MysqlStatement.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_MysqlStatement implements MWP_IncrementalBackup_Database_StatementInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var resource
|
16 |
+
*/
|
17 |
+
private $result;
|
18 |
+
|
19 |
+
public function __construct($result)
|
20 |
+
{
|
21 |
+
$this->result = $result;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return array|null
|
26 |
+
*/
|
27 |
+
public function fetch()
|
28 |
+
{
|
29 |
+
$row = @mysql_fetch_assoc($this->result);
|
30 |
+
if ($row === false) {
|
31 |
+
return null;
|
32 |
+
} else {
|
33 |
+
return $row;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return array|null
|
39 |
+
*/
|
40 |
+
public function fetchAll()
|
41 |
+
{
|
42 |
+
$rows = array();
|
43 |
+
|
44 |
+
while ($row = $this->fetch()) {
|
45 |
+
$rows[] = $row;
|
46 |
+
}
|
47 |
+
|
48 |
+
return $rows;
|
49 |
+
}
|
50 |
+
}
|
src/MWP/IncrementalBackup/Database/MysqliConnection.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_MysqliConnection implements MWP_IncrementalBackup_Database_ConnectionInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Database_Configuration
|
16 |
+
*/
|
17 |
+
private $configuration;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var mysqli
|
21 |
+
*/
|
22 |
+
private $connection;
|
23 |
+
|
24 |
+
public function __construct(MWP_IncrementalBackup_Database_Configuration $configuration)
|
25 |
+
{
|
26 |
+
$this->configuration = $configuration;
|
27 |
+
|
28 |
+
if (!extension_loaded('mysqli')) {
|
29 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException("Mysqli extension is not enabled.");
|
30 |
+
}
|
31 |
+
|
32 |
+
// Silence possible warnings thrown by mysqli
|
33 |
+
// e.g. Warning: mysqli::mysqli(): Headers and client library minor version mismatch. Headers:50540 Library:50623
|
34 |
+
$this->connection = @new mysqli($configuration->getHost(), $configuration->getUsername(), $configuration->getPassword(), $configuration->getDatabase(), $configuration->getPort());
|
35 |
+
|
36 |
+
if ($this->connection === null || !$this->connection->ping()) {
|
37 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException();
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->connection->set_charset($configuration->getCharset());
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @param string $query
|
45 |
+
*
|
46 |
+
* @throws MWP_IncrementalBackup_Database_Exception_ConnectionException
|
47 |
+
*
|
48 |
+
* @return MWP_IncrementalBackup_Database_StatementInterface
|
49 |
+
*/
|
50 |
+
public function query($query)
|
51 |
+
{
|
52 |
+
$result = $this->connection->query($query);
|
53 |
+
|
54 |
+
if ($result === false) {
|
55 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException($this->connection->error, $this->connection->errno);
|
56 |
+
}
|
57 |
+
|
58 |
+
return new MWP_IncrementalBackup_Database_MysqliStatement($result);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @param mixed $value any primitive value
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function quote($value)
|
67 |
+
{
|
68 |
+
return $this->connection->real_escape_string($value);
|
69 |
+
}
|
70 |
+
}
|
src/MWP/IncrementalBackup/Database/MysqliStatement.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_MysqliStatement implements MWP_IncrementalBackup_Database_StatementInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var mysqli_result|bool
|
16 |
+
*/
|
17 |
+
private $result;
|
18 |
+
|
19 |
+
public function __construct($result)
|
20 |
+
{
|
21 |
+
$this->result = $result;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return array|null
|
26 |
+
*/
|
27 |
+
public function fetch()
|
28 |
+
{
|
29 |
+
if (is_bool($this->result)) {
|
30 |
+
return $this->result;
|
31 |
+
}
|
32 |
+
|
33 |
+
return $this->result->fetch_assoc();
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @return array|null
|
38 |
+
*/
|
39 |
+
public function fetchAll()
|
40 |
+
{
|
41 |
+
if (is_bool($this->result)) {
|
42 |
+
return $this->result;
|
43 |
+
}
|
44 |
+
|
45 |
+
$rows = array();
|
46 |
+
while ($row = $this->fetch()) {
|
47 |
+
$rows[] = $row;
|
48 |
+
}
|
49 |
+
|
50 |
+
return $rows;
|
51 |
+
}
|
52 |
+
}
|
src/MWP/IncrementalBackup/Database/PdoConnection.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_PdoConnection implements MWP_IncrementalBackup_Database_ConnectionInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Database_Configuration
|
16 |
+
*/
|
17 |
+
private $configuration;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var PDO
|
21 |
+
*/
|
22 |
+
private $connection;
|
23 |
+
|
24 |
+
public function __construct(MWP_IncrementalBackup_Database_Configuration $configuration)
|
25 |
+
{
|
26 |
+
$this->configuration = $configuration;
|
27 |
+
|
28 |
+
if (!extension_loaded('pdo_mysql')) {
|
29 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException("PDO extension is disabled.");
|
30 |
+
}
|
31 |
+
|
32 |
+
$options = array(
|
33 |
+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
34 |
+
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
35 |
+
);
|
36 |
+
|
37 |
+
$this->connection = new PDO(self::getDsn($this->configuration), $this->configuration->getUsername(), $this->configuration->getPassword(), $options);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* {@inheritdoc}
|
42 |
+
*/
|
43 |
+
public function query($query)
|
44 |
+
{
|
45 |
+
return new MWP_IncrementalBackup_Database_PdoStatement($this->connection->query($query));
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* {@inheritdoc}
|
50 |
+
*/
|
51 |
+
public function quote($value)
|
52 |
+
{
|
53 |
+
return $this->connection->quote($value);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @param MWP_IncrementalBackup_Database_Configuration $configuration
|
58 |
+
*
|
59 |
+
* @return string
|
60 |
+
*/
|
61 |
+
private static function getDsn(MWP_IncrementalBackup_Database_Configuration $configuration)
|
62 |
+
{
|
63 |
+
$pdoParameters = array(
|
64 |
+
'dbname' => $configuration->getDatabase(),
|
65 |
+
'charset' => $configuration->getCharset(),
|
66 |
+
);
|
67 |
+
|
68 |
+
if ($configuration->isSocket()) {
|
69 |
+
$pdoParameters['unix_socket'] = $configuration->getSocketPath();
|
70 |
+
} else {
|
71 |
+
$pdoParameters['host'] = $configuration->getHost();
|
72 |
+
|
73 |
+
if (($port = $configuration->getPort()) !== null) {
|
74 |
+
$pdoParameters['port'] = $configuration->getPort();
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
$parameters = array();
|
79 |
+
foreach ($pdoParameters as $name => $value) {
|
80 |
+
$parameters[] = $name.'='.$value;
|
81 |
+
}
|
82 |
+
|
83 |
+
$dsn = sprintf("mysql:%s", implode(';', $parameters));
|
84 |
+
|
85 |
+
return $dsn;
|
86 |
+
}
|
87 |
+
}
|
src/MWP/IncrementalBackup/Database/PdoStatement.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_PdoStatement implements MWP_IncrementalBackup_Database_StatementInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var PDOStatement
|
16 |
+
*/
|
17 |
+
private $statement;
|
18 |
+
|
19 |
+
public function __construct(PDOStatement $statement)
|
20 |
+
{
|
21 |
+
$this->statement = $statement;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* {@inheritdoc}
|
26 |
+
*/
|
27 |
+
public function fetch()
|
28 |
+
{
|
29 |
+
return $this->statement->fetch();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* {@inheritdoc}
|
34 |
+
*/
|
35 |
+
public function fetchAll()
|
36 |
+
{
|
37 |
+
return $this->statement->fetchAll();
|
38 |
+
}
|
39 |
+
}
|
src/MWP/IncrementalBackup/Database/PhpDumper.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_PhpDumper implements MWP_IncrementalBackup_Database_DumperInterface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Database_Configuration
|
16 |
+
*/
|
17 |
+
private $configuration;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var MWP_System_Environment
|
21 |
+
*/
|
22 |
+
private $environment;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var MWP_IncrementalBackup_Database_DumpOptions
|
26 |
+
*/
|
27 |
+
private $options;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param MWP_IncrementalBackup_Database_Configuration $configuration
|
31 |
+
* @param MWP_System_Environment $environment
|
32 |
+
* @param MWP_IncrementalBackup_Database_DumpOptions $options
|
33 |
+
*/
|
34 |
+
public function __construct(MWP_IncrementalBackup_Database_Configuration $configuration, MWP_System_Environment $environment, MWP_IncrementalBackup_Database_DumpOptions $options)
|
35 |
+
{
|
36 |
+
$this->configuration = $configuration;
|
37 |
+
$this->environment = $environment;
|
38 |
+
$this->options = $options;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* {@inheritdoc}
|
43 |
+
*/
|
44 |
+
public function dump(array $tables)
|
45 |
+
{
|
46 |
+
if ($this->environment->isPdoEnabled()) {
|
47 |
+
$connection = new MWP_IncrementalBackup_Database_PdoConnection($this->configuration);
|
48 |
+
} elseif ($this->environment->isMysqliEnabled()) {
|
49 |
+
$connection = new MWP_IncrementalBackup_Database_MysqliConnection($this->configuration);
|
50 |
+
} elseif ($this->environment->isMysqlEnabled()) {
|
51 |
+
$connection = new MWP_IncrementalBackup_Database_MysqlConnection($this->configuration);
|
52 |
+
} else {
|
53 |
+
throw new MWP_IncrementalBackup_Database_Exception_ConnectionException("No mysql drivers available.");
|
54 |
+
}
|
55 |
+
|
56 |
+
$this->options->setTables($tables);
|
57 |
+
$dumper = new MWP_IncrementalBackup_Database_StreamableQuerySequenceDump($connection, $this->options);
|
58 |
+
|
59 |
+
return $dumper->createStream();
|
60 |
+
}
|
61 |
+
}
|
src/MWP/IncrementalBackup/Database/StatementInterface.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
interface MWP_IncrementalBackup_Database_StatementInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @return array|null
|
15 |
+
*/
|
16 |
+
public function fetch();
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @return array|null
|
20 |
+
*/
|
21 |
+
public function fetchAll();
|
22 |
+
}
|
src/MWP/IncrementalBackup/Database/StreamableQuerySequenceDump.php
ADDED
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Database_StreamableQuerySequenceDump
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Database_ConnectionInterface
|
16 |
+
*/
|
17 |
+
private $connection;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var MWP_IncrementalBackup_Database_DumpOptions
|
21 |
+
*/
|
22 |
+
private $options;
|
23 |
+
|
24 |
+
public function __construct(MWP_IncrementalBackup_Database_ConnectionInterface $connection, MWP_IncrementalBackup_Database_DumpOptions $options)
|
25 |
+
{
|
26 |
+
$this->connection = $connection;
|
27 |
+
$this->options = $options;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return MWP_IncrementalBackup_Database_ConnectionInterface
|
32 |
+
*/
|
33 |
+
protected function getConnection()
|
34 |
+
{
|
35 |
+
return $this->connection;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @inherit
|
40 |
+
*/
|
41 |
+
public function createStream()
|
42 |
+
{
|
43 |
+
$stream = new MWP_Stream_Append();
|
44 |
+
|
45 |
+
$stream->addStream(MWP_Stream_Stream::factory("
|
46 |
+
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
47 |
+
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
48 |
+
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
49 |
+
/*!40101 SET NAMES utf8 */;
|
50 |
+
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
51 |
+
/*!40103 SET TIME_ZONE='+00:00' */;
|
52 |
+
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
53 |
+
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
54 |
+
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
55 |
+
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n"
|
56 |
+
));
|
57 |
+
|
58 |
+
$allTables = MWP_Backup_ArrayHelper::arrayColumn($this->getConnection()->query('SHOW TABLES')->fetchAll());
|
59 |
+
$tables = array_intersect($allTables, $this->options->getTables() ? $this->options->getTables() : $allTables);
|
60 |
+
|
61 |
+
foreach ($tables as $tableName) {
|
62 |
+
$stream->addStream(
|
63 |
+
new MWP_Stream_Callable(array($this, 'streamCreateTable'), array($tableName))
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
$stream->addStream(MWP_Stream_Stream::factory("
|
68 |
+
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
69 |
+
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
70 |
+
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
71 |
+
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
72 |
+
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
73 |
+
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
74 |
+
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
75 |
+
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n"
|
76 |
+
));
|
77 |
+
|
78 |
+
return $stream;
|
79 |
+
}
|
80 |
+
|
81 |
+
public function streamCreateTable($length, $tableName)
|
82 |
+
{
|
83 |
+
// Get the SHOW CREATE TABLE part
|
84 |
+
$content = $this->getConnection()
|
85 |
+
->query("SHOW CREATE TABLE `{$tableName}`;")
|
86 |
+
->fetchAll();
|
87 |
+
|
88 |
+
if (!is_array($content)) {
|
89 |
+
return new MWP_Stream_Buffer();
|
90 |
+
}
|
91 |
+
|
92 |
+
$stream = new MWP_Stream_Append();
|
93 |
+
|
94 |
+
foreach ($content as $entry) {
|
95 |
+
// Add drop table query
|
96 |
+
if ($this->options->isDropTables()) {
|
97 |
+
$stream->addStream(MWP_Stream_Stream::factory("DROP TABLE IF EXISTS `$tableName`;\n"));
|
98 |
+
}
|
99 |
+
|
100 |
+
// Add create table query
|
101 |
+
$stream->addStream(MWP_Stream_Stream::factory("
|
102 |
+
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
103 |
+
/*!40101 SET character_set_client = utf8 */;\n"
|
104 |
+
));
|
105 |
+
$stream->addStream(MWP_Stream_Stream::factory($entry['Create Table'].";\n"));
|
106 |
+
$stream->addStream(MWP_Stream_Stream::factory("/*!40101 SET character_set_client = @saved_cs_client */;\n\n"));
|
107 |
+
}
|
108 |
+
|
109 |
+
// Export content
|
110 |
+
$stream->addStream(
|
111 |
+
new MWP_Stream_Callable(array($this, 'createExportTableStream'), array($tableName))
|
112 |
+
);
|
113 |
+
|
114 |
+
return $stream;
|
115 |
+
}
|
116 |
+
|
117 |
+
public function createExportTableStream($length, $tableName)
|
118 |
+
{
|
119 |
+
$stream = new MWP_Stream_Append();
|
120 |
+
|
121 |
+
$columns = $this->getConnection()
|
122 |
+
->query("SHOW COLUMNS IN `{$tableName}`;")
|
123 |
+
->fetchAll();
|
124 |
+
|
125 |
+
if (is_array($columns)) {
|
126 |
+
$columns = $this->repack($columns, 'Field');
|
127 |
+
}
|
128 |
+
|
129 |
+
$statement = $this->getConnection()
|
130 |
+
->query($this->selectAllDataQuery($tableName, $columns));
|
131 |
+
|
132 |
+
// Go through row by row
|
133 |
+
if (!$this->options->isSkipLockTables()) {
|
134 |
+
$stream->addStream(MWP_Stream_Stream::factory("LOCK TABLES `$tableName` WRITE;\n"));
|
135 |
+
}
|
136 |
+
|
137 |
+
$stream->addStream(MWP_Stream_Stream::factory("/*!40000 ALTER TABLE `$tableName` DISABLE KEYS */;\n"));
|
138 |
+
|
139 |
+
$stream->addStream(
|
140 |
+
new MWP_Stream_Callable(array($this, 'createExportRowStream'), array($statement, $tableName, $columns))
|
141 |
+
);
|
142 |
+
|
143 |
+
$stream->addStream(MWP_Stream_Stream::factory(";\n"));
|
144 |
+
$stream->addStream(MWP_Stream_Stream::factory("/*!40000 ALTER TABLE `$tableName` ENABLE KEYS */;\n"));
|
145 |
+
|
146 |
+
if (!$this->options->isSkipLockTables()) {
|
147 |
+
$stream->addStream(MWP_Stream_Stream::factory("UNLOCK TABLES;\n"));
|
148 |
+
}
|
149 |
+
|
150 |
+
return $stream;
|
151 |
+
}
|
152 |
+
|
153 |
+
public function createExportRowStream($length, MWP_IncrementalBackup_Database_StatementInterface $statement, $tableName, $columns)
|
154 |
+
{
|
155 |
+
$row = $statement->fetch();
|
156 |
+
if (!$row) {
|
157 |
+
return false;
|
158 |
+
}
|
159 |
+
|
160 |
+
return $this->createRowInsertStatement($tableName, $row, $columns);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Repacks an array by making a key of a particular column
|
165 |
+
*
|
166 |
+
* @param array $array
|
167 |
+
* @param $column
|
168 |
+
*
|
169 |
+
* @return array
|
170 |
+
*/
|
171 |
+
protected function repack(array $array, $column)
|
172 |
+
{
|
173 |
+
$repacked = array();
|
174 |
+
foreach ($array as $element) {
|
175 |
+
$repacked[$element[$column]] = $element;
|
176 |
+
}
|
177 |
+
|
178 |
+
return $repacked;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Creates an SQL statement for fetching all data from a particular table
|
183 |
+
*
|
184 |
+
* @param $tableName
|
185 |
+
* @param $columnData
|
186 |
+
*
|
187 |
+
* @return string
|
188 |
+
*/
|
189 |
+
protected function selectAllDataQuery($tableName, $columnData)
|
190 |
+
{
|
191 |
+
$columns = array();
|
192 |
+
foreach ($columnData as $columnName => $metadata) {
|
193 |
+
if (strpos($metadata['Type'], 'blob') !== false) {
|
194 |
+
$fullColumnName = "`{$tableName}`.`{$columnName}`";
|
195 |
+
$columns[] = "HEX($fullColumnName) as `{$columnName}`";
|
196 |
+
} else {
|
197 |
+
$columns[] = "`{$tableName}`.`{$columnName}`";
|
198 |
+
}
|
199 |
+
}
|
200 |
+
$cols = join(', ', $columns);
|
201 |
+
$sql = "SELECT $cols FROM `$tableName`;";
|
202 |
+
|
203 |
+
return $sql;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Creates an sql statement for row insertion
|
208 |
+
*
|
209 |
+
* @param string $tableName
|
210 |
+
* @param array $row
|
211 |
+
* @param array $columns
|
212 |
+
*
|
213 |
+
* @return string
|
214 |
+
*/
|
215 |
+
protected function createRowInsertStatement($tableName, array $row, array $columns = array())
|
216 |
+
{
|
217 |
+
$values = $this->createRowInsertValues($row, $columns);
|
218 |
+
$joined = join(', ', $values);
|
219 |
+
$sql = "INSERT INTO `$tableName` VALUES($joined);";
|
220 |
+
|
221 |
+
return $sql;
|
222 |
+
}
|
223 |
+
|
224 |
+
protected function createRowInsertValues($row, $columns)
|
225 |
+
{
|
226 |
+
$values = array();
|
227 |
+
|
228 |
+
foreach ($row as $columnName => $value) {
|
229 |
+
$type = $columns[$columnName]['Type'];
|
230 |
+
// If it should not be enclosed
|
231 |
+
if ($value === null) {
|
232 |
+
$values[] = 'null';
|
233 |
+
} elseif (strpos($type, 'int') !== false
|
234 |
+
|| strpos($type, 'float') !== false
|
235 |
+
|| strpos($type, 'double') !== false
|
236 |
+
|| strpos($type, 'decimal') !== false
|
237 |
+
|| strpos($type, 'bool') !== false
|
238 |
+
) {
|
239 |
+
$values[] = $value;
|
240 |
+
} elseif (strpos($type, 'blob') !== false) {
|
241 |
+
$values[] = strlen($value) ? ('0x'.$value) : "''";
|
242 |
+
} else {
|
243 |
+
$values[] = $this->getConnection()->quote($value);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
return $values;
|
248 |
+
}
|
249 |
+
}
|
src/MWP/IncrementalBackup/FileReader.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_FileReader
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var int
|
16 |
+
*/
|
17 |
+
private $chunkByteSize = 4096;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @return int
|
21 |
+
*/
|
22 |
+
public function getChunkByteSize()
|
23 |
+
{
|
24 |
+
return $this->chunkByteSize;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @param int $chunkByteSize
|
29 |
+
*/
|
30 |
+
public function setChunkByteSize($chunkByteSize)
|
31 |
+
{
|
32 |
+
$this->chunkByteSize = $chunkByteSize;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
*
|
37 |
+
*
|
38 |
+
* @param string $realPath
|
39 |
+
* @param int $offset
|
40 |
+
* @param int $limit
|
41 |
+
*
|
42 |
+
* @return mixed
|
43 |
+
*/
|
44 |
+
public function readFileContents($realPath, $offset = 0, $limit = 0)
|
45 |
+
{
|
46 |
+
if (!file_exists($realPath)) {
|
47 |
+
return null;
|
48 |
+
}
|
49 |
+
|
50 |
+
$handle = fopen($realPath, "rb");
|
51 |
+
if (!$handle) {
|
52 |
+
return null;
|
53 |
+
}
|
54 |
+
|
55 |
+
$contentLength = 0;
|
56 |
+
$buffer = '';
|
57 |
+
|
58 |
+
if ($limit === 0) {
|
59 |
+
$limit = filesize($realPath) - $offset;
|
60 |
+
}
|
61 |
+
|
62 |
+
if ($offset !== 0) {
|
63 |
+
fseek($handle, $offset);
|
64 |
+
}
|
65 |
+
|
66 |
+
while ($limit > 0) {
|
67 |
+
$chunkSize = $limit > $this->chunkByteSize ? $this->chunkByteSize : $limit;
|
68 |
+
$limit = $limit - $chunkSize;
|
69 |
+
$contentLength = $contentLength + $chunkSize;
|
70 |
+
|
71 |
+
$contents = fread($handle, $chunkSize);
|
72 |
+
$buffer = $buffer.$contents;
|
73 |
+
}
|
74 |
+
|
75 |
+
fclose($handle);
|
76 |
+
|
77 |
+
return array($buffer, $contentLength);
|
78 |
+
}
|
79 |
+
}
|
src/MWP/IncrementalBackup/HashComputer.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_HashComputer
|
12 |
+
{
|
13 |
+
|
14 |
+
// 100kb default value
|
15 |
+
private $maxChunkByteSize = 102400;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param int $maxChunkByteSize
|
19 |
+
*/
|
20 |
+
public function setMaxChunkByteSize($maxChunkByteSize)
|
21 |
+
{
|
22 |
+
$this->$maxChunkByteSize = $maxChunkByteSize;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return int
|
27 |
+
*/
|
28 |
+
public function getMaxChunkByteSize()
|
29 |
+
{
|
30 |
+
return $this->$maxChunkByteSize;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Compute a full md5 file hash or compute a partial hash if $limit is present.
|
35 |
+
* Returns null on failure.
|
36 |
+
*
|
37 |
+
* @param string $realPath
|
38 |
+
* @param int $offset in bytes
|
39 |
+
* @param int $limit in bytes
|
40 |
+
* @param boolean $forcePartialHashing
|
41 |
+
*
|
42 |
+
* @return null|string
|
43 |
+
*/
|
44 |
+
public function computeMd5Hash($realPath, $offset = 0, $limit = 0, $forcePartialHashing = false)
|
45 |
+
{
|
46 |
+
if ($limit === 0 && $offset === 0 && !$forcePartialHashing) {
|
47 |
+
// md5_file is always faster if we don't chunk the file
|
48 |
+
$hash = md5_file($realPath);
|
49 |
+
|
50 |
+
return $hash !== false ? $hash : null;
|
51 |
+
}
|
52 |
+
|
53 |
+
$ctx = hash_init('md5');
|
54 |
+
if (!$ctx) {
|
55 |
+
// Fail to initialize file hashing
|
56 |
+
return null;
|
57 |
+
}
|
58 |
+
|
59 |
+
// Calculate limit from file size and offset
|
60 |
+
if ($limit === 0) {
|
61 |
+
$limit = filesize($realPath) - $offset;
|
62 |
+
}
|
63 |
+
|
64 |
+
$fh = fopen($realPath, "rb");
|
65 |
+
if ($fh === null) {
|
66 |
+
// Failed opening file, cleanup hash context
|
67 |
+
hash_final($ctx);
|
68 |
+
|
69 |
+
return null;
|
70 |
+
}
|
71 |
+
|
72 |
+
fseek($fh, $offset);
|
73 |
+
|
74 |
+
while ($limit > 0) {
|
75 |
+
// Limit chunk size to either our remaining chunk or max chunk size
|
76 |
+
$chunkSize = $limit < $this->maxChunkByteSize ? $limit : $this->maxChunkByteSize;
|
77 |
+
$limit -= $chunkSize;
|
78 |
+
|
79 |
+
$chunk = fread($fh, $chunkSize);
|
80 |
+
hash_update($ctx, $chunk);
|
81 |
+
}
|
82 |
+
|
83 |
+
fclose($fh);
|
84 |
+
|
85 |
+
return hash_final($ctx);
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Run md5sum process and return file hash, or null in case of error
|
90 |
+
*
|
91 |
+
* @param $realPath
|
92 |
+
*
|
93 |
+
* @return string|null
|
94 |
+
*/
|
95 |
+
public function computeUnixMd5Sum($realPath)
|
96 |
+
{
|
97 |
+
try {
|
98 |
+
$processBuilder = Symfony_Process_ProcessBuilder::create()
|
99 |
+
->setPrefix('md5sum')
|
100 |
+
->add($realPath);
|
101 |
+
|
102 |
+
if (!mwp_is_shell_available()) {
|
103 |
+
throw new MMB_Exception("Shell is not available");
|
104 |
+
}
|
105 |
+
|
106 |
+
$process = $processBuilder->getProcess();
|
107 |
+
$process->run();
|
108 |
+
|
109 |
+
if (!$process->isSuccessful()) {
|
110 |
+
throw new Symfony_Process_Exception_ProcessFailedException($process);
|
111 |
+
}
|
112 |
+
|
113 |
+
// Output is in the format of "md5hash filename"
|
114 |
+
$output = trim($process->getOutput());
|
115 |
+
$parts = explode(' ', $output);
|
116 |
+
|
117 |
+
// Return only the first part of the output
|
118 |
+
return trim($parts[0]);
|
119 |
+
} catch (Symfony_Process_Exception_ProcessFailedException $e) {
|
120 |
+
mwp_logger()->error('MD5 command line sum failed', array(
|
121 |
+
'process' => $e->getProcess(),
|
122 |
+
));
|
123 |
+
} catch (Exception $e) {
|
124 |
+
mwp_logger()->error('MD5 command line sum failed', array(
|
125 |
+
'exception' => $e,
|
126 |
+
));
|
127 |
+
}
|
128 |
+
|
129 |
+
return null;
|
130 |
+
}
|
131 |
+
}
|
src/MWP/IncrementalBackup/Model/FetchFilesResult.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Model_FetchFilesResult
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_IncrementalBackup_Model_File[]
|
16 |
+
*/
|
17 |
+
private $files = array();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var MWP_IncrementalBackup_Model_ServerStatistics
|
21 |
+
*/
|
22 |
+
private $serverStatistics;
|
23 |
+
|
24 |
+
function __construct()
|
25 |
+
{
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @return MWP_IncrementalBackup_Model_File[]
|
30 |
+
*/
|
31 |
+
public function getFiles()
|
32 |
+
{
|
33 |
+
return $this->files;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @param MWP_IncrementalBackup_Model_File[] $files
|
38 |
+
*/
|
39 |
+
public function setFiles($files)
|
40 |
+
{
|
41 |
+
$this->files = $files;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param MWP_IncrementalBackup_Model_File $file
|
46 |
+
*/
|
47 |
+
public function addFile(MWP_IncrementalBackup_Model_File $file)
|
48 |
+
{
|
49 |
+
$this->files[] = $file;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @return MWP_IncrementalBackup_Model_ServerStatistics
|
54 |
+
*/
|
55 |
+
public function getServerStatistics()
|
56 |
+
{
|
57 |
+
return $this->serverStatistics;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @param MWP_IncrementalBackup_Model_ServerStatistics $serverStatistics
|
62 |
+
*/
|
63 |
+
public function setServerStatistics($serverStatistics)
|
64 |
+
{
|
65 |
+
$this->serverStatistics = $serverStatistics;
|
66 |
+
}
|
67 |
+
}
|
src/MWP/IncrementalBackup/Model/File.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Model_File
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
private $pathname;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var MWP_Stream_Interface
|
21 |
+
*/
|
22 |
+
private $stream;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return string
|
26 |
+
*/
|
27 |
+
public function getPathname()
|
28 |
+
{
|
29 |
+
return $this->pathname;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param string $pathname
|
34 |
+
*/
|
35 |
+
public function setPathname($pathname)
|
36 |
+
{
|
37 |
+
$this->pathname = $pathname;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return MWP_Stream_Interface
|
42 |
+
*/
|
43 |
+
public function getStream()
|
44 |
+
{
|
45 |
+
return $this->stream;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @param MWP_Stream_Interface $stream
|
50 |
+
*/
|
51 |
+
public function setStream($stream)
|
52 |
+
{
|
53 |
+
$this->stream = $stream;
|
54 |
+
}
|
55 |
+
}
|
src/MWP/IncrementalBackup/Model/ServerStatistics.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_IncrementalBackup_Model_ServerStatistics
|
12 |
+
{
|
13 |
+
|
14 |
+
/** @var int */
|
15 |
+
private $memoryPeak;
|
16 |
+
|
17 |
+
/** @var int */
|
18 |
+
private $memoryUsage;
|
19 |
+
|
20 |
+
/** @var int */
|
21 |
+
private $averageLoad;
|
22 |
+
|
23 |
+
/** @var bool */
|
24 |
+
private $shellAvailable;
|
25 |
+
|
26 |
+
function __construct($memoryPeak, $memoryUsage, $averageLoad, $shellAvailable)
|
27 |
+
{
|
28 |
+
$this->memoryPeak = $memoryPeak;
|
29 |
+
$this->memoryUsage = $memoryUsage;
|
30 |
+
$this->averageLoad = $averageLoad;
|
31 |
+
$this->shellAvailable = $shellAvailable;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return int
|
36 |
+
*/
|
37 |
+
public function getMemoryPeak()
|
38 |
+
{
|
39 |
+
return $this->memoryPeak;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @param int $memoryPeak
|
44 |
+
*/
|
45 |
+
public function setMemoryPeak($memoryPeak)
|
46 |
+
{
|
47 |
+
$this->memoryPeak = $memoryPeak;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @return int
|
52 |
+
*/
|
53 |
+
public function getMemoryUsage()
|
54 |
+
{
|
55 |
+
return $this->memoryUsage;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param int $memoryUsage
|
60 |
+
*/
|
61 |
+
public function setMemoryUsage($memoryUsage)
|
62 |
+
{
|
63 |
+
$this->memoryUsage = $memoryUsage;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @return int
|
68 |
+
*/
|
69 |
+
public function getAverageLoad()
|
70 |
+
{
|
71 |
+
return $this->averageLoad;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @param int $averageLoad
|
76 |
+
*/
|
77 |
+
public function setAverageLoad($averageLoad)
|
78 |
+
{
|
79 |
+
$this->averageLoad = $averageLoad;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @return boolean
|
84 |
+
*/
|
85 |
+
public function isShellAvailable()
|
86 |
+
{
|
87 |
+
return $this->shellAvailable;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* @param boolean $shellAvailable
|
92 |
+
*/
|
93 |
+
public function setShellAvailable($shellAvailable)
|
94 |
+
{
|
95 |
+
$this->shellAvailable = $shellAvailable;
|
96 |
+
}
|
97 |
+
|
98 |
+
public function toArray()
|
99 |
+
{
|
100 |
+
return array(
|
101 |
+
'memory_peak' => $this->getMemoryPeak(),
|
102 |
+
'memory_usage' => $this->getMemoryUsage(),
|
103 |
+
'average_load' => $this->getAverageLoad(),
|
104 |
+
'shell_available' => $this->isShellAvailable(),
|
105 |
+
);
|
106 |
+
}
|
107 |
+
|
108 |
+
public static function factory()
|
109 |
+
{
|
110 |
+
return new self(
|
111 |
+
memory_get_peak_usage(true),
|
112 |
+
memory_get_usage(true),
|
113 |
+
strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? array(0, 0, 0) : sys_getloadavg(),
|
114 |
+
mwp_is_shell_available()
|
115 |
+
);
|
116 |
+
}
|
117 |
+
}
|
src/MWP/ServiceContainer/Abstract.php
CHANGED
@@ -59,6 +59,12 @@ abstract class MWP_ServiceContainer_Abstract implements MWP_ServiceContainer_Int
|
|
59 |
|
60 |
private $errorLogger;
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
public function __construct(array $parameters = array())
|
63 |
{
|
64 |
$this->parameters = $parameters;
|
@@ -70,6 +76,14 @@ abstract class MWP_ServiceContainer_Abstract implements MWP_ServiceContainer_Int
|
|
70 |
'worker_basename' => null,
|
71 |
// Always use PhpSecLib, even if the PHP extension 'openssl' is loaded.
|
72 |
'prefer_phpseclib' => false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
// Log file to use for all worker logs.
|
74 |
'log_file' => null,
|
75 |
// GrayLog2 server to use for all worker logs.
|
@@ -83,6 +97,9 @@ abstract class MWP_ServiceContainer_Abstract implements MWP_ServiceContainer_Int
|
|
83 |
'message_minimum_level' => Monolog_Logger::INFO,
|
84 |
// Memory size (in kilobytes) to allocate for fatal error handling when the request is authenticated.
|
85 |
'fatal_error_reserved_memory_size' => 1024,
|
|
|
|
|
|
|
86 |
'hit_counter_blacklisted_ips' => array(
|
87 |
// Uptime monitoring robot.
|
88 |
'/^74\.86\.158\.106$/',
|
@@ -487,4 +504,43 @@ abstract class MWP_ServiceContainer_Abstract implements MWP_ServiceContainer_Int
|
|
487 |
* @return Monolog_Logger
|
488 |
*/
|
489 |
protected abstract function createErrorLogger();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
}
|
59 |
|
60 |
private $errorLogger;
|
61 |
|
62 |
+
private $systemEnvironment;
|
63 |
+
|
64 |
+
private $updaterSkin;
|
65 |
+
|
66 |
+
private $sessionStore;
|
67 |
+
|
68 |
public function __construct(array $parameters = array())
|
69 |
{
|
70 |
$this->parameters = $parameters;
|
76 |
'worker_basename' => null,
|
77 |
// Always use PhpSecLib, even if the PHP extension 'openssl' is loaded.
|
78 |
'prefer_phpseclib' => false,
|
79 |
+
// Force using fallbacks instead of shell commands
|
80 |
+
'disable_shell' => false,
|
81 |
+
// Emulate disabled PDO extension
|
82 |
+
'disable_pdo' => false,
|
83 |
+
// Emulate disabled mysqli extension
|
84 |
+
'disable_mysqli' => false,
|
85 |
+
// Emulate disabled mysql
|
86 |
+
'disable_mysql' => false,
|
87 |
// Log file to use for all worker logs.
|
88 |
'log_file' => null,
|
89 |
// GrayLog2 server to use for all worker logs.
|
97 |
'message_minimum_level' => Monolog_Logger::INFO,
|
98 |
// Memory size (in kilobytes) to allocate for fatal error handling when the request is authenticated.
|
99 |
'fatal_error_reserved_memory_size' => 1024,
|
100 |
+
// This boundary will be different with each request and it's pretty much a hack for handling exceptions
|
101 |
+
// @see MWP_EventListener_ActionException_MultipartException
|
102 |
+
'multipart_boundary' => uniqid(),
|
103 |
'hit_counter_blacklisted_ips' => array(
|
104 |
// Uptime monitoring robot.
|
105 |
'/^74\.86\.158\.106$/',
|
504 |
* @return Monolog_Logger
|
505 |
*/
|
506 |
protected abstract function createErrorLogger();
|
507 |
+
|
508 |
+
public function getSystemEnvironment()
|
509 |
+
{
|
510 |
+
if ($this->systemEnvironment === null) {
|
511 |
+
$this->systemEnvironment = $this->createSystemEnvironment();
|
512 |
+
}
|
513 |
+
|
514 |
+
return $this->systemEnvironment;
|
515 |
+
}
|
516 |
+
|
517 |
+
protected abstract function createSystemEnvironment();
|
518 |
+
|
519 |
+
public function getUpdaterSkin()
|
520 |
+
{
|
521 |
+
if ($this->updaterSkin === null) {
|
522 |
+
$this->updaterSkin = $this->createUpdaterSkin();
|
523 |
+
}
|
524 |
+
|
525 |
+
return $this->updaterSkin;
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* @return MWP_Updater_TraceableUpdaterSkin
|
530 |
+
*/
|
531 |
+
protected abstract function createUpdaterSkin();
|
532 |
+
|
533 |
+
public function getSessionStore()
|
534 |
+
{
|
535 |
+
if ($this->sessionStore === null) {
|
536 |
+
$this->sessionStore = $this->createSessionStore();
|
537 |
+
}
|
538 |
+
|
539 |
+
return $this->sessionStore;
|
540 |
+
}
|
541 |
+
|
542 |
+
/**
|
543 |
+
* @return MWP_WordPress_SessionStore
|
544 |
+
*/
|
545 |
+
protected abstract function createSessionStore();
|
546 |
}
|
src/MWP/ServiceContainer/Interface.php
CHANGED
@@ -138,4 +138,19 @@ interface MWP_ServiceContainer_Interface
|
|
138 |
* @return Monolog_Logger
|
139 |
*/
|
140 |
public function getErrorLogger();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
}
|
138 |
* @return Monolog_Logger
|
139 |
*/
|
140 |
public function getErrorLogger();
|
141 |
+
|
142 |
+
/**
|
143 |
+
* @return MWP_System_Environment
|
144 |
+
*/
|
145 |
+
public function getSystemEnvironment();
|
146 |
+
|
147 |
+
/**
|
148 |
+
* @return MWP_Updater_TraceableUpdaterSkin
|
149 |
+
*/
|
150 |
+
public function getUpdaterSkin();
|
151 |
+
|
152 |
+
/**
|
153 |
+
* @return MWP_WordPress_SessionStore
|
154 |
+
*/
|
155 |
+
public function getSessionStore();
|
156 |
}
|
src/MWP/ServiceContainer/Production.php
CHANGED
@@ -25,29 +25,39 @@ class MWP_ServiceContainer_Production extends MWP_ServiceContainer_Abstract
|
|
25 |
{
|
26 |
$dispatcher = new Symfony_EventDispatcher_EventDispatcher();
|
27 |
|
28 |
-
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_BrandContactSupport($this->getWordPressContext(), $this->getBrand()));
|
29 |
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_DisableEditor($this->getWordPressContext(), $this->getBrand()));
|
30 |
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_SetPluginInfo($this->getWordPressContext(), $this->getBrand()));
|
31 |
-
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_SetHitCounter($this->getWordPressContext(), $this->getHitCounter(), $this->getParameter('hit_counter_blacklisted_ips'), $this->getParameter('hit_counter_blacklisted_user_agents')));
|
32 |
-
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_AutomaticLogin($this->getWordPressContext(), $this->getNonceManager(), $this->getSigner(), $this->getConfiguration()));
|
|
|
33 |
|
34 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_VerifyConnectionInfo($this->getWordPressContext(), $this->getSigner()));
|
35 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_VerifyNonce($this->getNonceManager()));
|
36 |
-
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_SetCurrentUser($this->getWordPressContext()));
|
37 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AuthenticateRequest($this->getConfiguration(), $this->getSigner()));
|
38 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_SetErrorHandler($this->getErrorLogger(), $this->getErrorHandler(), $this->getRequestStack(), $this->getResponseCallback(), $this, $this->getParameter('log_errors'), $this->getParameter('fatal_error_reserved_memory_size')));
|
39 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AttachJsonMessageHandler($this->getLogger(), $this->getJsonMessageHandler()));
|
40 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_RemoveUsernameParam());
|
41 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AuthenticateLegacyRequest($this->getConfiguration()));
|
|
|
42 |
|
43 |
-
$dispatcher->addSubscriber(new
|
|
|
|
|
44 |
|
45 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionException_SetExceptionData());
|
|
|
46 |
|
47 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetActionData());
|
48 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetLegacyWebsiteConnectionData($this->getWordPressContext()));
|
49 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_ChainState($this));
|
|
|
50 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetLegacyPhpExecutionData());
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
$dispatcher->addSubscriber(new MWP_EventListener_EncodeMasterResponse());
|
53 |
|
@@ -66,43 +76,55 @@ class MWP_ServiceContainer_Production extends MWP_ServiceContainer_Abstract
|
|
66 |
{
|
67 |
$mapper = new MWP_Action_Registry();
|
68 |
|
69 |
-
$mapper->addDefinition('do_upgrade', new MWP_Action_Definition('mmb_do_upgrade', array('hook_name' => '
|
70 |
-
$mapper->addDefinition('get_stats', new MWP_Action_Definition('mmb_stats_get', array('hook_name' => '
|
71 |
$mapper->addDefinition('remove_site', new MWP_Action_Definition('mmb_remove_site'));
|
72 |
$mapper->addDefinition('backup_clone', new MWP_Action_Definition('mmb_backup_now'));
|
73 |
$mapper->addDefinition('restore', new MWP_Action_Definition('mmb_restore_now'));
|
74 |
-
$mapper->addDefinition('create_post', new MWP_Action_Definition('mmb_post_create', array('hook_name' => '
|
75 |
$mapper->addDefinition('update_worker', new MWP_Action_Definition('mmb_update_worker_plugin'));
|
76 |
-
$mapper->addDefinition('change_post_status', new MWP_Action_Definition('mmb_change_post_status', array('hook_name' => '
|
77 |
-
$mapper->addDefinition('install_addon', new MWP_Action_Definition('mmb_install_addon', array('hook_name' => '
|
78 |
-
$mapper->addDefinition('get_comments', new MWP_Action_Definition('mmb_get_comments', array('hook_name' => '
|
79 |
-
$mapper->addDefinition('bulk_action_comments', new MWP_Action_Definition('mmb_bulk_action_comments', array('hook_name' => '
|
80 |
-
$mapper->addDefinition('replyto_comment', new MWP_Action_Definition('mmb_reply_comment', array('hook_name' => '
|
81 |
-
$mapper->addDefinition('add_user', new MWP_Action_Definition('mmb_add_user', array('hook_name' => '
|
82 |
$mapper->addDefinition('scheduled_backup', new MWP_Action_Definition('mmb_scheduled_backup'));
|
83 |
$mapper->addDefinition('run_task', new MWP_Action_Definition('mmb_run_task_now'));
|
84 |
$mapper->addDefinition('execute_php_code', new MWP_Action_Definition('mmb_execute_php_code'));
|
85 |
$mapper->addDefinition('delete_backup', new MWP_Action_Definition('mmm_delete_backup'));
|
86 |
$mapper->addDefinition('remote_backup_now', new MWP_Action_Definition('mmb_remote_backup_now'));
|
87 |
-
$mapper->addDefinition('get_users', new MWP_Action_Definition('mmb_get_users', array('hook_name' => '
|
88 |
-
$mapper->addDefinition('edit_users', new MWP_Action_Definition('mmb_edit_users', array('hook_name' => '
|
89 |
-
$mapper->addDefinition('get_posts', new MWP_Action_Definition('mmb_get_posts', array('hook_name' => '
|
90 |
-
$mapper->addDefinition('delete_post', new MWP_Action_Definition('mmb_delete_post', array('hook_name' => '
|
91 |
-
$mapper->addDefinition('delete_posts', new MWP_Action_Definition('mmb_delete_posts', array('hook_name' => '
|
92 |
-
$mapper->addDefinition('get_pages', new MWP_Action_Definition('mmb_get_pages', array('hook_name' => '
|
93 |
-
$mapper->addDefinition('delete_page', new MWP_Action_Definition('mmb_delete_page', array('hook_name' => '
|
94 |
-
$mapper->addDefinition('get_plugins_themes', new MWP_Action_Definition('mmb_get_plugins_themes', array('hook_name' => '
|
95 |
-
$mapper->addDefinition('edit_plugins_themes', new MWP_Action_Definition('mmb_edit_plugins_themes', array('hook_name' => '
|
96 |
$mapper->addDefinition('worker_brand', new MWP_Action_Definition('mmb_worker_brand'));
|
97 |
$mapper->addDefinition('maintenance', new MWP_Action_Definition('mmb_maintenance_mode'));
|
98 |
$mapper->addDefinition('get_autoupdate_plugins_themes', new MWP_Action_Definition('mmb_get_autoupdate_plugins_themes'));
|
99 |
$mapper->addDefinition('edit_autoupdate_plugins_themes', new MWP_Action_Definition('mmb_edit_autoupdate_plugins_themes'));
|
100 |
$mapper->addDefinition('ping_backup', new MWP_Action_Definition('mwp_ping_backup'));
|
101 |
-
$mapper->addDefinition('cleanup_delete', new MWP_Action_Definition('cleanup_delete_worker'));
|
102 |
$mapper->addDefinition('backup_req', new MWP_Action_Definition('mmb_get_backup_req'));
|
103 |
-
$mapper->addDefinition('change_comment_status', new MWP_Action_Definition('mmb_change_comment_status', array('hook_name' =>
|
104 |
$mapper->addDefinition('get_state', new MWP_Action_Definition(array('MWP_Action_GetState', 'execute')));
|
105 |
$mapper->addDefinition('add_site', new MWP_Action_Definition(array('MWP_Action_ConnectWebsite', 'execute')));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
return $mapper;
|
108 |
}
|
@@ -219,6 +241,8 @@ class MWP_ServiceContainer_Production extends MWP_ServiceContainer_Abstract
|
|
219 |
array(new MWP_Monolog_Processor_ExceptionProcessor(), 'callback'),
|
220 |
array(new MWP_Monolog_Processor_ProcessProcessor(), 'callback'),
|
221 |
);
|
|
|
|
|
222 |
}
|
223 |
|
224 |
$logger = new Monolog_Logger('worker', $handlers, $processors);
|
@@ -261,7 +285,7 @@ class MWP_ServiceContainer_Production extends MWP_ServiceContainer_Abstract
|
|
261 |
*/
|
262 |
protected function createHitCounter()
|
263 |
{
|
264 |
-
$counter = new MWP_Extension_HitCounter($this->getWordPressContext(),
|
265 |
|
266 |
return $counter;
|
267 |
}
|
@@ -290,4 +314,28 @@ class MWP_ServiceContainer_Production extends MWP_ServiceContainer_Abstract
|
|
290 |
|
291 |
return $logger;
|
292 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
}
|
25 |
{
|
26 |
$dispatcher = new Symfony_EventDispatcher_EventDispatcher();
|
27 |
|
28 |
+
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_BrandContactSupport($this->getWordPressContext(), $this->getBrand(), $this->getRequestStack()));
|
29 |
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_DisableEditor($this->getWordPressContext(), $this->getBrand()));
|
30 |
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_SetPluginInfo($this->getWordPressContext(), $this->getBrand()));
|
31 |
+
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_SetHitCounter($this->getWordPressContext(), $this->getHitCounter(), $this->getRequestStack(), $this->getParameter('hit_counter_blacklisted_ips'), $this->getParameter('hit_counter_blacklisted_user_agents')));
|
32 |
+
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_AutomaticLogin($this->getWordPressContext(), $this->getNonceManager(), $this->getSigner(), $this->getConfiguration(), $this->getSessionStore()));
|
33 |
+
$dispatcher->addSubscriber(new MWP_EventListener_PublicRequest_AddStatusPage($this->getWordPressContext(), $this->getConfiguration()));
|
34 |
|
35 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_VerifyConnectionInfo($this->getWordPressContext(), $this->getSigner()));
|
36 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_VerifyNonce($this->getNonceManager()));
|
|
|
37 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AuthenticateRequest($this->getConfiguration(), $this->getSigner()));
|
38 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_SetErrorHandler($this->getErrorLogger(), $this->getErrorHandler(), $this->getRequestStack(), $this->getResponseCallback(), $this, $this->getParameter('log_errors'), $this->getParameter('fatal_error_reserved_memory_size')));
|
39 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AttachJsonMessageHandler($this->getLogger(), $this->getJsonMessageHandler()));
|
40 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_RemoveUsernameParam());
|
41 |
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_AuthenticateLegacyRequest($this->getConfiguration()));
|
42 |
+
$dispatcher->addSubscriber(new MWP_EventListener_MasterRequest_SetRequestSettings($this->getWordPressContext()));
|
43 |
|
44 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionRequest_SetCurrentUser($this->getWordPressContext()));
|
45 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionRequest_SetSettings($this->getWordPressContext(), $this->getSystemEnvironment()));
|
46 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionRequest_LogRequest($this->getLogger()));
|
47 |
|
48 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionException_SetExceptionData());
|
49 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionException_MultipartException($this->getParameter('multipart_boundary')));
|
50 |
|
51 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetActionData());
|
52 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetLegacyWebsiteConnectionData($this->getWordPressContext()));
|
53 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_ChainState($this));
|
54 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetUpdaterLog($this->getUpdaterSkin()));
|
55 |
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_SetLegacyPhpExecutionData());
|
56 |
+
$dispatcher->addSubscriber(new MWP_EventListener_ActionResponse_FetchFiles($this->getParameter('multipart_boundary')));
|
57 |
+
|
58 |
+
$dispatcher->addSubscriber(new MWP_EventListener_MasterResponse_LogResponse($this->getLogger()));
|
59 |
+
|
60 |
+
$dispatcher->addSubscriber(new MWP_EventListener_FixCompatibility($this->getWordPressContext()));
|
61 |
|
62 |
$dispatcher->addSubscriber(new MWP_EventListener_EncodeMasterResponse());
|
63 |
|
76 |
{
|
77 |
$mapper = new MWP_Action_Registry();
|
78 |
|
79 |
+
$mapper->addDefinition('do_upgrade', new MWP_Action_Definition('mmb_do_upgrade', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
80 |
+
$mapper->addDefinition('get_stats', new MWP_Action_Definition('mmb_stats_get', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
81 |
$mapper->addDefinition('remove_site', new MWP_Action_Definition('mmb_remove_site'));
|
82 |
$mapper->addDefinition('backup_clone', new MWP_Action_Definition('mmb_backup_now'));
|
83 |
$mapper->addDefinition('restore', new MWP_Action_Definition('mmb_restore_now'));
|
84 |
+
$mapper->addDefinition('create_post', new MWP_Action_Definition('mmb_post_create', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
85 |
$mapper->addDefinition('update_worker', new MWP_Action_Definition('mmb_update_worker_plugin'));
|
86 |
+
$mapper->addDefinition('change_post_status', new MWP_Action_Definition('mmb_change_post_status', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
87 |
+
$mapper->addDefinition('install_addon', new MWP_Action_Definition('mmb_install_addon', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
88 |
+
$mapper->addDefinition('get_comments', new MWP_Action_Definition('mmb_get_comments', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
89 |
+
$mapper->addDefinition('bulk_action_comments', new MWP_Action_Definition('mmb_bulk_action_comments', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
90 |
+
$mapper->addDefinition('replyto_comment', new MWP_Action_Definition('mmb_reply_comment', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
91 |
+
$mapper->addDefinition('add_user', new MWP_Action_Definition('mmb_add_user', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
92 |
$mapper->addDefinition('scheduled_backup', new MWP_Action_Definition('mmb_scheduled_backup'));
|
93 |
$mapper->addDefinition('run_task', new MWP_Action_Definition('mmb_run_task_now'));
|
94 |
$mapper->addDefinition('execute_php_code', new MWP_Action_Definition('mmb_execute_php_code'));
|
95 |
$mapper->addDefinition('delete_backup', new MWP_Action_Definition('mmm_delete_backup'));
|
96 |
$mapper->addDefinition('remote_backup_now', new MWP_Action_Definition('mmb_remote_backup_now'));
|
97 |
+
$mapper->addDefinition('get_users', new MWP_Action_Definition('mmb_get_users', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
98 |
+
$mapper->addDefinition('edit_users', new MWP_Action_Definition('mmb_edit_users', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
99 |
+
$mapper->addDefinition('get_posts', new MWP_Action_Definition('mmb_get_posts', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
100 |
+
$mapper->addDefinition('delete_post', new MWP_Action_Definition('mmb_delete_post', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
101 |
+
$mapper->addDefinition('delete_posts', new MWP_Action_Definition('mmb_delete_posts', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
102 |
+
$mapper->addDefinition('get_pages', new MWP_Action_Definition('mmb_get_pages', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
103 |
+
$mapper->addDefinition('delete_page', new MWP_Action_Definition('mmb_delete_page', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
104 |
+
$mapper->addDefinition('get_plugins_themes', new MWP_Action_Definition('mmb_get_plugins_themes', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
105 |
+
$mapper->addDefinition('edit_plugins_themes', new MWP_Action_Definition('mmb_edit_plugins_themes', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
106 |
$mapper->addDefinition('worker_brand', new MWP_Action_Definition('mmb_worker_brand'));
|
107 |
$mapper->addDefinition('maintenance', new MWP_Action_Definition('mmb_maintenance_mode'));
|
108 |
$mapper->addDefinition('get_autoupdate_plugins_themes', new MWP_Action_Definition('mmb_get_autoupdate_plugins_themes'));
|
109 |
$mapper->addDefinition('edit_autoupdate_plugins_themes', new MWP_Action_Definition('mmb_edit_autoupdate_plugins_themes'));
|
110 |
$mapper->addDefinition('ping_backup', new MWP_Action_Definition('mwp_ping_backup'));
|
111 |
+
$mapper->addDefinition('cleanup_delete', new MWP_Action_Definition('cleanup_delete_worker', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
112 |
$mapper->addDefinition('backup_req', new MWP_Action_Definition('mmb_get_backup_req'));
|
113 |
+
$mapper->addDefinition('change_comment_status', new MWP_Action_Definition('mmb_change_comment_status', array('hook_name' => 'init', 'hook_priority' => 9999)));
|
114 |
$mapper->addDefinition('get_state', new MWP_Action_Definition(array('MWP_Action_GetState', 'execute')));
|
115 |
$mapper->addDefinition('add_site', new MWP_Action_Definition(array('MWP_Action_ConnectWebsite', 'execute')));
|
116 |
+
$mapper->addDefinition('destroy_sessions', new MWP_Action_Definition(array('MWP_Action_DestroySessions', 'execute')));
|
117 |
+
|
118 |
+
// Incremental backup actions
|
119 |
+
$mapper->addDefinition('list_files', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_ListFiles', 'queryFiles')));
|
120 |
+
$mapper->addDefinition('list_directories', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_ListFiles', 'listDirectories')));
|
121 |
+
$mapper->addDefinition('hash_files', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_HashFiles', 'execute')));
|
122 |
+
$mapper->addDefinition('fetch_files', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_FetchFiles', 'execute')));
|
123 |
+
$mapper->addDefinition('list_tables', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_ListTables', 'listTables')));
|
124 |
+
$mapper->addDefinition('checksum_tables', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_ChecksumTables', 'execute')));
|
125 |
+
$mapper->addDefinition('dump_tables', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_DumpTables', 'execute')));
|
126 |
+
$mapper->addDefinition('backup_stats', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_Stats', 'execute')));
|
127 |
+
$mapper->addDefinition('upload_cloner', new MWP_Action_Definition(array('MWP_Action_IncrementalBackup_UploadCloner', 'execute')));
|
128 |
|
129 |
return $mapper;
|
130 |
}
|
241 |
array(new MWP_Monolog_Processor_ExceptionProcessor(), 'callback'),
|
242 |
array(new MWP_Monolog_Processor_ProcessProcessor(), 'callback'),
|
243 |
);
|
244 |
+
} else {
|
245 |
+
$handlers[] = new Monolog_Handler_NullHandler();
|
246 |
}
|
247 |
|
248 |
$logger = new Monolog_Logger('worker', $handlers, $processors);
|
285 |
*/
|
286 |
protected function createHitCounter()
|
287 |
{
|
288 |
+
$counter = new MWP_Extension_HitCounter($this->getWordPressContext(), 60);
|
289 |
|
290 |
return $counter;
|
291 |
}
|
314 |
|
315 |
return $logger;
|
316 |
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* @return MWP_System_Environment
|
320 |
+
*/
|
321 |
+
protected function createSystemEnvironment()
|
322 |
+
{
|
323 |
+
return new MWP_System_Environment($this);
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* @return MWP_Updater_TraceableUpdaterSkin
|
328 |
+
*/
|
329 |
+
protected function createUpdaterSkin()
|
330 |
+
{
|
331 |
+
return new MWP_Updater_TraceableUpdaterSkin();
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* @return MWP_WordPress_SessionStore
|
336 |
+
*/
|
337 |
+
protected function createSessionStore()
|
338 |
+
{
|
339 |
+
return new MWP_WordPress_SessionStore($this->getWordPressContext());
|
340 |
+
}
|
341 |
}
|
src/MWP/Signer/PhpSecLibSigner.php
CHANGED
@@ -23,8 +23,10 @@ class MWP_Signer_PhpSecLibSigner implements MWP_Signer_Interface
|
|
23 |
$verify = $rsa->verify($data, $signature);
|
24 |
$errorMessage = $errorCatcher->yieldErrorMessage(true);
|
25 |
|
26 |
-
if ($errorMessage !== null && $errorMessage !== 'Signature representative out of range') {
|
27 |
-
throw new MWP_Worker_Exception(MWP_Worker_Exception::PHPSECLIB_VERIFY_ERROR
|
|
|
|
|
28 |
}
|
29 |
|
30 |
return $verify;
|
23 |
$verify = $rsa->verify($data, $signature);
|
24 |
$errorMessage = $errorCatcher->yieldErrorMessage(true);
|
25 |
|
26 |
+
if ($errorMessage !== null && $errorMessage !== 'Signature representative out of range' && $errorMessage !== 'Invalid signature') {
|
27 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::PHPSECLIB_VERIFY_ERROR, null, array(
|
28 |
+
'error' => $errorMessage,
|
29 |
+
));
|
30 |
}
|
31 |
|
32 |
return $verify;
|
src/MWP/Stream/Append.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Append stream.
|
13 |
+
*/
|
14 |
+
class MWP_Stream_Append implements MWP_Stream_Interface
|
15 |
+
{
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var MWP_Stream_Interface[]
|
19 |
+
*/
|
20 |
+
private $streams = array();
|
21 |
+
|
22 |
+
private $current = 0;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Add a stream to the AppendStream
|
26 |
+
*
|
27 |
+
* @param MWP_Stream_Interface $stream Stream to append. Must be readable.
|
28 |
+
*/
|
29 |
+
public function addStream(MWP_Stream_Interface $stream)
|
30 |
+
{
|
31 |
+
$this->streams[] = $stream;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return bool
|
36 |
+
*/
|
37 |
+
public function isSeekable()
|
38 |
+
{
|
39 |
+
return false;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* {@inheritdoc}
|
44 |
+
*/
|
45 |
+
public function seek($offset, $whence = SEEK_SET)
|
46 |
+
{
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* {@inheritdoc}
|
52 |
+
*/
|
53 |
+
public function eof()
|
54 |
+
{
|
55 |
+
return $this->isAtLastStream() && $this->getCurrentStream()->eof();
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* {@inheritdoc}
|
60 |
+
*/
|
61 |
+
public function read($length)
|
62 |
+
{
|
63 |
+
$data = '';
|
64 |
+
|
65 |
+
while (!$this->eof()) {
|
66 |
+
while ($this->getCurrentStream()->eof() && !$this->eof()) {
|
67 |
+
$this->moveToNextStream();
|
68 |
+
}
|
69 |
+
|
70 |
+
$currentStreamData = $this->getCurrentStream()->read($length);
|
71 |
+
$data .= $currentStreamData;
|
72 |
+
$length -= strlen($currentStreamData);
|
73 |
+
|
74 |
+
if ($length <= 0) {
|
75 |
+
break;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
return $data;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* {@inheritdoc}
|
84 |
+
*/
|
85 |
+
public function close()
|
86 |
+
{
|
87 |
+
foreach ($this->streams as $stream) {
|
88 |
+
$stream->close();
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Tell is not supported.
|
94 |
+
*/
|
95 |
+
public function tell()
|
96 |
+
{
|
97 |
+
return false;
|
98 |
+
}
|
99 |
+
|
100 |
+
public function __toString()
|
101 |
+
{
|
102 |
+
$buffer = '';
|
103 |
+
|
104 |
+
while (!$this->eof()) {
|
105 |
+
$buffer .= $this->read(1048576);
|
106 |
+
}
|
107 |
+
|
108 |
+
return $buffer;
|
109 |
+
}
|
110 |
+
|
111 |
+
private function moveToNextStream()
|
112 |
+
{
|
113 |
+
if ($this->current >= count($this->streams)) {
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
|
117 |
+
$this->current++;
|
118 |
+
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
|
122 |
+
private function isAtLastStream()
|
123 |
+
{
|
124 |
+
return $this->current === count($this->streams) - 1;
|
125 |
+
}
|
126 |
+
|
127 |
+
private function getCurrentStream()
|
128 |
+
{
|
129 |
+
return $this->streams[$this->current];
|
130 |
+
}
|
131 |
+
}
|
src/MWP/Stream/Buffer.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Stream_Buffer
|
12 |
+
{
|
13 |
+
|
14 |
+
private $hwm;
|
15 |
+
|
16 |
+
private $buffer = '';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param int $hwm High water mark, representing the preferred maximum
|
20 |
+
* buffer size. If the size of the buffer exceeds the high
|
21 |
+
* water mark, then calls to write will continue to succeed
|
22 |
+
* but will return false to inform writers to slow down
|
23 |
+
* until the buffer has been drained by reading from it.
|
24 |
+
*/
|
25 |
+
public function __construct($hwm = 16384)
|
26 |
+
{
|
27 |
+
$this->hwm = $hwm;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function close()
|
31 |
+
{
|
32 |
+
$this->buffer = '';
|
33 |
+
}
|
34 |
+
|
35 |
+
public function isSeekable()
|
36 |
+
{
|
37 |
+
return false;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function seek($offset, $whence = SEEK_SET)
|
41 |
+
{
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function eof()
|
46 |
+
{
|
47 |
+
return strlen($this->buffer) === 0;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function tell()
|
51 |
+
{
|
52 |
+
return false;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Reads data from the buffer.
|
57 |
+
*
|
58 |
+
* @param $length
|
59 |
+
*
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
public function read($length)
|
63 |
+
{
|
64 |
+
$currentLength = strlen($this->buffer);
|
65 |
+
|
66 |
+
if ($length >= $currentLength) {
|
67 |
+
// No need to slice the buffer because we don't have enough data.
|
68 |
+
$result = $this->buffer;
|
69 |
+
$this->buffer = '';
|
70 |
+
} else {
|
71 |
+
// Slice up the result to provide a subset of the buffer.
|
72 |
+
$result = substr($this->buffer, 0, $length);
|
73 |
+
$this->buffer = substr($this->buffer, $length);
|
74 |
+
}
|
75 |
+
|
76 |
+
return $result;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Writes data to the buffer.
|
81 |
+
*
|
82 |
+
* @param $string
|
83 |
+
*
|
84 |
+
* @return bool|int
|
85 |
+
*/
|
86 |
+
public function write($string)
|
87 |
+
{
|
88 |
+
$this->buffer .= $string;
|
89 |
+
|
90 |
+
if (strlen($this->buffer) >= $this->hwm) {
|
91 |
+
return false;
|
92 |
+
}
|
93 |
+
|
94 |
+
return strlen($string);
|
95 |
+
}
|
96 |
+
}
|
src/MWP/Stream/Callable.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Stream_Callable implements MWP_Stream_Interface
|
12 |
+
{
|
13 |
+
|
14 |
+
/** @var callable */
|
15 |
+
private $source;
|
16 |
+
|
17 |
+
/** @var int */
|
18 |
+
private $tellPos = 0;
|
19 |
+
|
20 |
+
/** @var MWP_Stream_Buffer */
|
21 |
+
private $buffer;
|
22 |
+
|
23 |
+
/** @var array */
|
24 |
+
private $arguments;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @param callable $source Source of the stream data. The callable MAY
|
28 |
+
* accept an integer argument used to control the
|
29 |
+
* amount of data to return. The callable MUST
|
30 |
+
* return a string when called, or false on error
|
31 |
+
* or EOF.
|
32 |
+
* @param array $arguments
|
33 |
+
*/
|
34 |
+
public function __construct($source, array $arguments = array())
|
35 |
+
{
|
36 |
+
$this->source = $source;
|
37 |
+
$this->buffer = new MWP_Stream_Buffer();
|
38 |
+
$this->arguments = $arguments;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function close()
|
42 |
+
{
|
43 |
+
$this->tellPos = false;
|
44 |
+
$this->source = null;
|
45 |
+
$this->arguments = array();
|
46 |
+
}
|
47 |
+
|
48 |
+
public function tell()
|
49 |
+
{
|
50 |
+
return $this->tellPos;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function eof()
|
54 |
+
{
|
55 |
+
return !$this->source;
|
56 |
+
}
|
57 |
+
|
58 |
+
public function isSeekable()
|
59 |
+
{
|
60 |
+
return false;
|
61 |
+
}
|
62 |
+
|
63 |
+
public function seek($offset, $whence = SEEK_SET)
|
64 |
+
{
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
|
68 |
+
public function read($length)
|
69 |
+
{
|
70 |
+
$data = $this->buffer->read($length);
|
71 |
+
$readLen = strlen($data);
|
72 |
+
$this->tellPos += $readLen;
|
73 |
+
$remaining = $length - $readLen;
|
74 |
+
|
75 |
+
if ($remaining) {
|
76 |
+
$this->pump($remaining);
|
77 |
+
$data .= $this->buffer->read($remaining);
|
78 |
+
$this->tellPos += strlen($data) - $readLen;
|
79 |
+
}
|
80 |
+
|
81 |
+
return $data;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function __toString()
|
85 |
+
{
|
86 |
+
$buffer = '';
|
87 |
+
|
88 |
+
while (!$this->eof()) {
|
89 |
+
$buffer .= $this->read(1048576);
|
90 |
+
}
|
91 |
+
|
92 |
+
return $buffer;
|
93 |
+
}
|
94 |
+
|
95 |
+
private function pump($length)
|
96 |
+
{
|
97 |
+
if ($this->source) {
|
98 |
+
do {
|
99 |
+
$data = call_user_func_array($this->source, array_merge(array($length), $this->arguments));
|
100 |
+
if ($data === false || $data === null) {
|
101 |
+
$this->source = null;
|
102 |
+
|
103 |
+
return;
|
104 |
+
}
|
105 |
+
if ($data instanceof MWP_Stream_Interface) {
|
106 |
+
$this->source = null;
|
107 |
+
$this->buffer = $data;
|
108 |
+
|
109 |
+
return;
|
110 |
+
}
|
111 |
+
$this->buffer->write($data);
|
112 |
+
$length -= strlen($data);
|
113 |
+
} while ($length > 0);
|
114 |
+
}
|
115 |
+
}
|
116 |
+
}
|
src/MWP/Stream/Interface.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
interface MWP_Stream_Interface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Closes the stream and any underlying resources.
|
15 |
+
*/
|
16 |
+
public function close();
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Returns the current position of the file read/write pointer
|
20 |
+
*
|
21 |
+
* @return int|bool Returns the position of the file pointer or false on error
|
22 |
+
*/
|
23 |
+
public function tell();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
+
public function isSeekable();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param int $offset
|
32 |
+
* @param int $whence
|
33 |
+
*
|
34 |
+
* @return bool
|
35 |
+
*/
|
36 |
+
public function seek($offset, $whence = SEEK_SET);
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Returns true if the stream is at the end of the stream.
|
40 |
+
*
|
41 |
+
* @return bool
|
42 |
+
*/
|
43 |
+
public function eof();
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Read data from the stream
|
47 |
+
*
|
48 |
+
* @param int $length Read up to $length bytes from the object and return
|
49 |
+
* them. Fewer than $length bytes may be returned if
|
50 |
+
* underlying stream call returns fewer bytes.
|
51 |
+
*
|
52 |
+
* @return string Returns the data read from the stream.
|
53 |
+
*/
|
54 |
+
public function read($length);
|
55 |
+
}
|
src/MWP/Stream/LazyFile.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Lazily open file stream for reading and close it when EOF is reached.
|
13 |
+
*/
|
14 |
+
class MWP_Stream_LazyFile implements MWP_Stream_Interface
|
15 |
+
{
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var MWP_Stream_Interface
|
19 |
+
*/
|
20 |
+
private $stream = null;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var mixed
|
24 |
+
*/
|
25 |
+
private $realPath;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var bool
|
29 |
+
*/
|
30 |
+
private $initialized = false;
|
31 |
+
|
32 |
+
public function __construct($realPath)
|
33 |
+
{
|
34 |
+
$this->realPath = $realPath;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* {@inheritdoc}
|
39 |
+
*/
|
40 |
+
public function close()
|
41 |
+
{
|
42 |
+
if ($this->stream !== null) {
|
43 |
+
$this->stream->close();
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* {@inheritdoc}
|
49 |
+
*/
|
50 |
+
public function tell()
|
51 |
+
{
|
52 |
+
$this->initialize();
|
53 |
+
|
54 |
+
return $this->stream !== null ? $this->stream->tell() : false;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* {@inheritdoc}
|
59 |
+
*/
|
60 |
+
public function isSeekable()
|
61 |
+
{
|
62 |
+
$this->initialize();
|
63 |
+
|
64 |
+
return $this->stream !== null ? $this->stream->isSeekable() : false;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* {@inheritdoc}
|
69 |
+
*/
|
70 |
+
public function seek($offset, $whence = SEEK_SET)
|
71 |
+
{
|
72 |
+
$this->initialize();
|
73 |
+
|
74 |
+
return $this->stream !== null ? $this->stream->seek($offset, $whence) : false;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* {@inheritdoc}
|
79 |
+
*/
|
80 |
+
public function eof()
|
81 |
+
{
|
82 |
+
$this->initialize();
|
83 |
+
|
84 |
+
return $this->stream !== null ? $this->stream->eof() : true;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* {@inheritdoc}
|
89 |
+
*/
|
90 |
+
public function read($length)
|
91 |
+
{
|
92 |
+
$this->initialize();
|
93 |
+
|
94 |
+
if ($this->stream === null) {
|
95 |
+
return null;
|
96 |
+
}
|
97 |
+
|
98 |
+
$data = $this->stream->read($length);
|
99 |
+
|
100 |
+
if ($this->eof()) {
|
101 |
+
$this->close();
|
102 |
+
}
|
103 |
+
|
104 |
+
return $data;
|
105 |
+
}
|
106 |
+
|
107 |
+
public function __toString()
|
108 |
+
{
|
109 |
+
$buffer = '';
|
110 |
+
|
111 |
+
while (!$this->eof()) {
|
112 |
+
$buffer .= $this->read(1048576);
|
113 |
+
}
|
114 |
+
|
115 |
+
return $buffer;
|
116 |
+
}
|
117 |
+
|
118 |
+
private function initialize()
|
119 |
+
{
|
120 |
+
if ($this->initialized === false) {
|
121 |
+
if (file_exists($this->realPath)) {
|
122 |
+
$handle = @fopen($this->realPath, "rb");
|
123 |
+
if ($handle !== false) {
|
124 |
+
$this->stream = MWP_Stream_Stream::factory($handle);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
$this->initialized = true;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
src/MWP/Stream/Limit.php
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Stream_Limit implements MWP_Stream_Interface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_Stream_Interface
|
16 |
+
*/
|
17 |
+
private $stream;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
private $offset = 0;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var int
|
26 |
+
*/
|
27 |
+
private $limit = -1;
|
28 |
+
|
29 |
+
public function __construct(MWP_Stream_Interface $stream, $offset = 0, $limit = -1)
|
30 |
+
{
|
31 |
+
$this->stream = $stream;
|
32 |
+
$this->setOffset($offset);
|
33 |
+
$this->limit = $limit;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* {@inheritdoc}
|
38 |
+
*/
|
39 |
+
public function eof()
|
40 |
+
{
|
41 |
+
// Always return true if the underlying stream is EOF
|
42 |
+
if ($this->stream->eof()) {
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
|
46 |
+
// No limit and the underlying stream is not at EOF
|
47 |
+
if ($this->limit == -1) {
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
$tell = $this->stream->tell();
|
52 |
+
if ($tell === false) {
|
53 |
+
return false;
|
54 |
+
}
|
55 |
+
|
56 |
+
return $tell >= $this->offset + $this->limit;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* {@inheritdoc}
|
61 |
+
*/
|
62 |
+
public function read($length)
|
63 |
+
{
|
64 |
+
if ($this->limit == -1) {
|
65 |
+
return $this->stream->read($length);
|
66 |
+
}
|
67 |
+
|
68 |
+
// Check if the current position is less than the total allowed
|
69 |
+
// bytes + original offset
|
70 |
+
$remaining = ($this->offset + $this->limit) - $this->stream->tell();
|
71 |
+
if ($remaining > 0) {
|
72 |
+
// Only return the amount of requested data, ensuring that the byte
|
73 |
+
// limit is not exceeded
|
74 |
+
return $this->stream->read(min($remaining, $length));
|
75 |
+
} else {
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* {@inheritdoc}
|
82 |
+
*/
|
83 |
+
public function setOffset($offset)
|
84 |
+
{
|
85 |
+
$current = $this->stream->tell();
|
86 |
+
|
87 |
+
if ($current !== $offset) {
|
88 |
+
// If the stream cannot seek to the offset position, then read to it
|
89 |
+
if (!$this->stream->seek($offset)) {
|
90 |
+
$this->stream->read($offset - $current);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
$this->offset = $offset;
|
95 |
+
|
96 |
+
return $this;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* {@inheritdoc}
|
101 |
+
*/
|
102 |
+
public function tell()
|
103 |
+
{
|
104 |
+
return $this->stream->tell() - $this->offset;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* {@inheritdoc}
|
109 |
+
*/
|
110 |
+
public function isSeekable()
|
111 |
+
{
|
112 |
+
return $this->stream->isSeekable();
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* {@inheritdoc}
|
117 |
+
*/
|
118 |
+
public function seek($offset, $whence = SEEK_SET)
|
119 |
+
{
|
120 |
+
if ($whence !== SEEK_SET || $offset < 0) {
|
121 |
+
return false;
|
122 |
+
}
|
123 |
+
|
124 |
+
$offset += $this->offset;
|
125 |
+
|
126 |
+
if ($this->limit !== -1) {
|
127 |
+
if ($offset > $this->offset + $this->limit) {
|
128 |
+
$offset = $this->offset + $this->limit;
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
return $this->stream->seek($offset);
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* {@inheritdoc}
|
137 |
+
*/
|
138 |
+
public function close()
|
139 |
+
{
|
140 |
+
$this->stream->close();
|
141 |
+
}
|
142 |
+
|
143 |
+
public function __toString()
|
144 |
+
{
|
145 |
+
$buffer = '';
|
146 |
+
|
147 |
+
while (!$this->eof()) {
|
148 |
+
$buffer .= $this->read(1048576);
|
149 |
+
}
|
150 |
+
|
151 |
+
return $buffer;
|
152 |
+
}
|
153 |
+
}
|
src/MWP/Stream/ProcessOutput.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Stream_ProcessOutput extends MWP_Stream_Callable
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var Symfony_Process_Process
|
16 |
+
*/
|
17 |
+
private $process;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var bool
|
21 |
+
*/
|
22 |
+
private $ran = false;
|
23 |
+
|
24 |
+
public function __construct(Symfony_Process_Process $process)
|
25 |
+
{
|
26 |
+
parent::__construct(array($this, 'getIncrementalOutput'));
|
27 |
+
$this->process = $process;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getIncrementalOutput()
|
31 |
+
{
|
32 |
+
if (!$this->ran) {
|
33 |
+
$this->ran = true;
|
34 |
+
try {
|
35 |
+
$this->process->start();
|
36 |
+
} catch (Symfony_Process_Exception_ExceptionInterface $e) {
|
37 |
+
throw new Symfony_Process_Exception_ProcessFailedException($this->process);
|
38 |
+
}
|
39 |
+
usleep(100);
|
40 |
+
}
|
41 |
+
|
42 |
+
$output = $this->process->getIncrementalOutput();
|
43 |
+
if (!$this->process->isRunning() && empty($output)) {
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
|
47 |
+
return empty($output) ? '' : $output;
|
48 |
+
}
|
49 |
+
}
|
src/MWP/Stream/Stream.php
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_Stream_Stream implements MWP_Stream_Interface
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var resource
|
16 |
+
*/
|
17 |
+
private $stream;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var bool
|
21 |
+
*/
|
22 |
+
private $seekable;
|
23 |
+
|
24 |
+
public function __construct($stream)
|
25 |
+
{
|
26 |
+
if (!is_resource($stream)) {
|
27 |
+
throw new \InvalidArgumentException('Stream must be a resource');
|
28 |
+
}
|
29 |
+
|
30 |
+
$this->stream = $stream;
|
31 |
+
|
32 |
+
$meta = stream_get_meta_data($this->stream);
|
33 |
+
$this->seekable = $meta['seekable'];
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Returns true if the stream is at the end of the stream.
|
38 |
+
*
|
39 |
+
* @return bool
|
40 |
+
*/
|
41 |
+
public function eof()
|
42 |
+
{
|
43 |
+
return !$this->stream || feof($this->stream);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Read data from the stream
|
48 |
+
*
|
49 |
+
* @param int $length Read up to $length bytes from the object and return
|
50 |
+
* them. Fewer than $length bytes may be returned if
|
51 |
+
* underlying stream call returns fewer bytes.
|
52 |
+
*
|
53 |
+
* @return string Returns the data read from the stream.
|
54 |
+
*/
|
55 |
+
public function read($length)
|
56 |
+
{
|
57 |
+
return fread($this->stream, $length);
|
58 |
+
}
|
59 |
+
|
60 |
+
public static function factory($resource)
|
61 |
+
{
|
62 |
+
$type = gettype($resource);
|
63 |
+
|
64 |
+
if ($type == 'string') {
|
65 |
+
$stream = fopen('php://temp', 'r+');
|
66 |
+
if ($resource !== '') {
|
67 |
+
fwrite($stream, $resource);
|
68 |
+
fseek($stream, 0);
|
69 |
+
}
|
70 |
+
|
71 |
+
return new self($stream);
|
72 |
+
}
|
73 |
+
|
74 |
+
if ($type == 'resource') {
|
75 |
+
return new self($resource);
|
76 |
+
}
|
77 |
+
|
78 |
+
if ($resource instanceof MWP_Stream_Interface) {
|
79 |
+
return $resource;
|
80 |
+
}
|
81 |
+
|
82 |
+
throw new InvalidArgumentException('Invalid resource type: '.$type);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* {@inheritdoc}
|
87 |
+
*/
|
88 |
+
public function isSeekable()
|
89 |
+
{
|
90 |
+
return $this->seekable;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* {@inheritdoc}
|
95 |
+
*/
|
96 |
+
public function seek($offset, $whence = SEEK_SET)
|
97 |
+
{
|
98 |
+
return $this->seekable
|
99 |
+
? fseek($this->stream, $offset, $whence) === 0
|
100 |
+
: false;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* {@inheritdoc}
|
105 |
+
*/
|
106 |
+
public function close()
|
107 |
+
{
|
108 |
+
if ($this->stream !== null) {
|
109 |
+
fclose($this->stream);
|
110 |
+
$this->stream = null;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* {@inheritdoc}
|
116 |
+
*/
|
117 |
+
public function tell()
|
118 |
+
{
|
119 |
+
return $this->stream !== null ? ftell($this->stream) : false;
|
120 |
+
}
|
121 |
+
|
122 |
+
public function __toString()
|
123 |
+
{
|
124 |
+
$buffer = '';
|
125 |
+
|
126 |
+
while (!$this->eof()) {
|
127 |
+
$buffer .= $this->read(1048576);
|
128 |
+
}
|
129 |
+
|
130 |
+
return $buffer;
|
131 |
+
}
|
132 |
+
}
|
src/MWP/System/Environment.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_System_Environment
|
12 |
+
{
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var MWP_ServiceContainer_Interface
|
16 |
+
*/
|
17 |
+
private $container;
|
18 |
+
|
19 |
+
public function __construct(MWP_ServiceContainer_Interface $container)
|
20 |
+
{
|
21 |
+
$this->container = $container;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getMemoryLimit()
|
25 |
+
{
|
26 |
+
return MWP_System_Utils::convertToBytes(ini_get('memory_limit'));
|
27 |
+
}
|
28 |
+
|
29 |
+
public function isPdoEnabled()
|
30 |
+
{
|
31 |
+
if ($this->container->getParameter('disable_pdo')) {
|
32 |
+
return false;
|
33 |
+
}
|
34 |
+
|
35 |
+
return extension_loaded('pdo_mysql');
|
36 |
+
}
|
37 |
+
|
38 |
+
public function isMysqliEnabled()
|
39 |
+
{
|
40 |
+
if ($this->container->getParameter('disable_mysqli')) {
|
41 |
+
return false;
|
42 |
+
}
|
43 |
+
|
44 |
+
return extension_loaded('mysqli');
|
45 |
+
}
|
46 |
+
|
47 |
+
public function isMysqlEnabled()
|
48 |
+
{
|
49 |
+
if ($this->container->getParameter('disable_mysql')) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
return extension_loaded('mysql');
|
54 |
+
}
|
55 |
+
}
|
src/MWP/System/Utils.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_System_Utils
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Converts output of 'memory_limit' php.ini directive to bytes.
|
15 |
+
*
|
16 |
+
* @param $memoryLimit
|
17 |
+
*
|
18 |
+
* @return int|string
|
19 |
+
*/
|
20 |
+
public static function convertToBytes($memoryLimit)
|
21 |
+
{
|
22 |
+
if ('-1' === $memoryLimit) {
|
23 |
+
return -1;
|
24 |
+
}
|
25 |
+
|
26 |
+
$memoryLimit = strtolower($memoryLimit);
|
27 |
+
$max = strtolower(ltrim($memoryLimit, '+'));
|
28 |
+
if (0 === strpos($max, '0x')) {
|
29 |
+
$max = intval($max, 16);
|
30 |
+
} elseif (0 === strpos($max, '0')) {
|
31 |
+
$max = intval($max, 8);
|
32 |
+
} else {
|
33 |
+
$max = intval($max);
|
34 |
+
}
|
35 |
+
|
36 |
+
switch (substr($memoryLimit, -1)) {
|
37 |
+
case 't':
|
38 |
+
$max *= 1024;
|
39 |
+
case 'g':
|
40 |
+
$max *= 1024;
|
41 |
+
case 'm':
|
42 |
+
$max *= 1024;
|
43 |
+
case 'k':
|
44 |
+
$max *= 1024;
|
45 |
+
}
|
46 |
+
|
47 |
+
return $max;
|
48 |
+
}
|
49 |
+
}
|
src/MWP/Updater/TraceableUpdaterSkin.php
ADDED
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Taken from WordPress's automatic updater skin, which was added in version 3.7.
|
13 |
+
*
|
14 |
+
* @see Automatic_Upgrader_Skin
|
15 |
+
*/
|
16 |
+
class MWP_Updater_TraceableUpdaterSkin
|
17 |
+
{
|
18 |
+
|
19 |
+
public $options = array(
|
20 |
+
'url' => '',
|
21 |
+
'nonce' => '',
|
22 |
+
'title' => '',
|
23 |
+
'context' => false,
|
24 |
+
);
|
25 |
+
|
26 |
+
public $upgrader;
|
27 |
+
|
28 |
+
public $result;
|
29 |
+
|
30 |
+
public $done_header = false;
|
31 |
+
|
32 |
+
protected $messages = array();
|
33 |
+
|
34 |
+
public function request_filesystem_credentials($error = false, $context = '', $allow_relaxed_file_ownership = false)
|
35 |
+
{
|
36 |
+
if ($error instanceof WP_Error) {
|
37 |
+
throw new MWP_Worker_Exception(MWP_Worker_Exception::FILESYSTEM_CREDENTIALS_ERROR, $error->get_error_message());
|
38 |
+
}
|
39 |
+
|
40 |
+
if ($context) {
|
41 |
+
$this->options['context'] = $context;
|
42 |
+
}
|
43 |
+
|
44 |
+
require_once ABSPATH.'wp-admin/includes/file.php';
|
45 |
+
// This will output a credentials form in event of failure; we don't want that, so just hide with a buffer.
|
46 |
+
ob_start();
|
47 |
+
$result = request_filesystem_credentials('', '', $error, $context, null, $allow_relaxed_file_ownership);
|
48 |
+
ob_end_clean();
|
49 |
+
|
50 |
+
return $result;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function get_upgrade_messages()
|
54 |
+
{
|
55 |
+
return $this->messages;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param string|array|WP_Error $data
|
60 |
+
*/
|
61 |
+
public function feedback($data)
|
62 |
+
{
|
63 |
+
if (is_wp_error($data)) {
|
64 |
+
$string = $data->get_error_message();
|
65 |
+
} else {
|
66 |
+
if (is_array($data)) {
|
67 |
+
return;
|
68 |
+
} else {
|
69 |
+
$string = $data;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
if (!empty($this->upgrader->strings[$string])) {
|
74 |
+
$string = $this->upgrader->strings[$string];
|
75 |
+
}
|
76 |
+
|
77 |
+
if (strpos($string, '%') !== false) {
|
78 |
+
$args = func_get_args();
|
79 |
+
$args = array_splice($args, 1);
|
80 |
+
if (!empty($args)) {
|
81 |
+
$string = vsprintf($string, $args);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
$string = trim($string);
|
86 |
+
|
87 |
+
// Only allow basic HTML in the messages, as it'll be used in emails/logs rather than direct browser output.
|
88 |
+
$string = wp_kses($string, array(
|
89 |
+
'a' => array(
|
90 |
+
'href' => true
|
91 |
+
),
|
92 |
+
'br' => true,
|
93 |
+
'em' => true,
|
94 |
+
'strong' => true,
|
95 |
+
));
|
96 |
+
|
97 |
+
if (empty($string)) {
|
98 |
+
return;
|
99 |
+
}
|
100 |
+
|
101 |
+
$this->messages[] = array(
|
102 |
+
'message' => $string,
|
103 |
+
'key' => $data,
|
104 |
+
'args' => isset($args) ? $args : array(),
|
105 |
+
);
|
106 |
+
}
|
107 |
+
|
108 |
+
public function header()
|
109 |
+
{
|
110 |
+
ob_start();
|
111 |
+
}
|
112 |
+
|
113 |
+
public function footer()
|
114 |
+
{
|
115 |
+
$output = ob_get_contents();
|
116 |
+
if (!empty($output)) {
|
117 |
+
$this->feedback($output);
|
118 |
+
}
|
119 |
+
ob_end_clean();
|
120 |
+
}
|
121 |
+
|
122 |
+
public function bulk_header()
|
123 |
+
{
|
124 |
+
}
|
125 |
+
|
126 |
+
public function bulk_footer()
|
127 |
+
{
|
128 |
+
}
|
129 |
+
|
130 |
+
public function before()
|
131 |
+
{
|
132 |
+
}
|
133 |
+
|
134 |
+
public function after()
|
135 |
+
{
|
136 |
+
}
|
137 |
+
|
138 |
+
// Below was taken from WP_Upgrader_Skin, so we don't autoload it and cause trouble.
|
139 |
+
public function decrement_update_count()
|
140 |
+
{
|
141 |
+
}
|
142 |
+
|
143 |
+
public function error($errors)
|
144 |
+
{
|
145 |
+
if (is_string($errors)) {
|
146 |
+
$this->feedback($errors);
|
147 |
+
|
148 |
+
return;
|
149 |
+
}
|
150 |
+
|
151 |
+
if (!$errors instanceof WP_Error || !$errors->get_error_code()) {
|
152 |
+
return;
|
153 |
+
}
|
154 |
+
|
155 |
+
foreach ($errors->get_error_messages() as $message) {
|
156 |
+
if ($errors->get_error_data() && is_string($errors->get_error_data())) {
|
157 |
+
$this->feedback($message.' '.esc_html(strip_tags($errors->get_error_data())));
|
158 |
+
} else {
|
159 |
+
$this->feedback($message);
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* @param WP_Upgrader $upgrader
|
166 |
+
*/
|
167 |
+
public function set_upgrader($upgrader)
|
168 |
+
{
|
169 |
+
if (is_object($upgrader)) {
|
170 |
+
$this->upgrader = $upgrader;
|
171 |
+
}
|
172 |
+
$this->add_strings();
|
173 |
+
}
|
174 |
+
|
175 |
+
public function add_strings()
|
176 |
+
{
|
177 |
+
}
|
178 |
+
|
179 |
+
public function set_result($result)
|
180 |
+
{
|
181 |
+
$this->result = $result;
|
182 |
+
}
|
183 |
+
}
|
src/MWP/WordPress/Context.php
CHANGED
@@ -288,6 +288,21 @@ class MWP_WordPress_Context
|
|
288 |
return get_themes();
|
289 |
}
|
290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
public function getStylesheetDirectory()
|
292 |
{
|
293 |
return get_stylesheet_directory();
|
@@ -397,6 +412,9 @@ class MWP_WordPress_Context
|
|
397 |
|
398 |
public function isGranted($capability)
|
399 |
{
|
|
|
|
|
|
|
400 |
return current_user_can($capability);
|
401 |
}
|
402 |
|
@@ -460,7 +478,7 @@ class MWP_WordPress_Context
|
|
460 |
/**
|
461 |
* @param string $username
|
462 |
*
|
463 |
-
* @return WP_User|null
|
464 |
*/
|
465 |
public function getUserByUsername($username)
|
466 |
{
|
@@ -478,7 +496,7 @@ class MWP_WordPress_Context
|
|
478 |
/**
|
479 |
* @param $criteria
|
480 |
*
|
481 |
-
* @return WP_User[]
|
482 |
*
|
483 |
* @link http://codex.wordpress.org/Function_Reference/get_users
|
484 |
*
|
@@ -512,7 +530,10 @@ class MWP_WordPress_Context
|
|
512 |
return in_array($pluginBasename, $plugins);
|
513 |
}
|
514 |
|
515 |
-
|
|
|
|
|
|
|
516 |
{
|
517 |
$this->requirePluggable();
|
518 |
|
@@ -523,7 +544,12 @@ class MWP_WordPress_Context
|
|
523 |
wp_set_current_user($user->ID);
|
524 |
}
|
525 |
|
526 |
-
|
|
|
|
|
|
|
|
|
|
|
527 |
{
|
528 |
$this->requireCookieConstants();
|
529 |
|
@@ -671,4 +697,51 @@ class MWP_WordPress_Context
|
|
671 |
{
|
672 |
remove_action($tag, $function, $priority);
|
673 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
674 |
}
|
288 |
return get_themes();
|
289 |
}
|
290 |
|
291 |
+
public function getCurrentTheme()
|
292 |
+
{
|
293 |
+
// When the plugin is MU-loaded, the WordPress theme directories are not set.
|
294 |
+
if ($this->isMustUse() && empty($this->context['wp_theme_directories'])) {
|
295 |
+
// Register the default theme directory root.
|
296 |
+
register_theme_directory(get_theme_root());
|
297 |
+
}
|
298 |
+
|
299 |
+
if ($this->isVersionAtLeast('3.4')) {
|
300 |
+
return wp_get_theme();
|
301 |
+
}
|
302 |
+
|
303 |
+
return get_current_theme();
|
304 |
+
}
|
305 |
+
|
306 |
public function getStylesheetDirectory()
|
307 |
{
|
308 |
return get_stylesheet_directory();
|
412 |
|
413 |
public function isGranted($capability)
|
414 |
{
|
415 |
+
$this->requirePluggable();
|
416 |
+
$this->requireCookieConstants();
|
417 |
+
|
418 |
return current_user_can($capability);
|
419 |
}
|
420 |
|
478 |
/**
|
479 |
* @param string $username
|
480 |
*
|
481 |
+
* @return WP_User|stdClass|null
|
482 |
*/
|
483 |
public function getUserByUsername($username)
|
484 |
{
|
496 |
/**
|
497 |
* @param $criteria
|
498 |
*
|
499 |
+
* @return WP_User[]|stdClass[]
|
500 |
*
|
501 |
* @link http://codex.wordpress.org/Function_Reference/get_users
|
502 |
*
|
530 |
return in_array($pluginBasename, $plugins);
|
531 |
}
|
532 |
|
533 |
+
/**
|
534 |
+
* @param WP_User|stdClass $user
|
535 |
+
*/
|
536 |
+
public function setCurrentUser($user)
|
537 |
{
|
538 |
$this->requirePluggable();
|
539 |
|
544 |
wp_set_current_user($user->ID);
|
545 |
}
|
546 |
|
547 |
+
/**
|
548 |
+
* @param WP_User|stdClass $user
|
549 |
+
* @param bool $remember
|
550 |
+
* @param string $secure
|
551 |
+
*/
|
552 |
+
public function setAuthCookie($user, $remember = false, $secure = '')
|
553 |
{
|
554 |
$this->requireCookieConstants();
|
555 |
|
697 |
{
|
698 |
remove_action($tag, $function, $priority);
|
699 |
}
|
700 |
+
|
701 |
+
public function addSubMenuPage($parentSlug, $pageTitle, $menuTitle, $capability, $menuSlug, $function = '')
|
702 |
+
{
|
703 |
+
return add_submenu_page($parentSlug, $pageTitle, $menuTitle, $capability, $menuSlug, $function);
|
704 |
+
}
|
705 |
+
|
706 |
+
public function wpNonceUrl($url, $action = -1, $name = '_wpnonce')
|
707 |
+
{
|
708 |
+
return wp_nonce_url($url, $action, $name);
|
709 |
+
}
|
710 |
+
|
711 |
+
/**
|
712 |
+
* @param int $userId
|
713 |
+
* @param string $metaKey
|
714 |
+
*
|
715 |
+
* @return mixed
|
716 |
+
*/
|
717 |
+
public function getUserMeta($userId, $metaKey)
|
718 |
+
{
|
719 |
+
return get_user_meta($userId, $metaKey, true);
|
720 |
+
}
|
721 |
+
|
722 |
+
/**
|
723 |
+
* @param int $userId
|
724 |
+
* @param string $metaKey
|
725 |
+
* @param mixed $metaValue
|
726 |
+
*
|
727 |
+
* @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
|
728 |
+
*/
|
729 |
+
public function setUserMeta($userId, $metaKey, $metaValue)
|
730 |
+
{
|
731 |
+
return update_user_meta($userId, $metaKey, $metaValue);
|
732 |
+
}
|
733 |
+
|
734 |
+
/**
|
735 |
+
* @param int $userId
|
736 |
+
*
|
737 |
+
* @return WP_Session_Tokens|null Returns null if the class does not exist, ie. before WordPress version 4.0.0.
|
738 |
+
*/
|
739 |
+
public function getSessionTokens($userId)
|
740 |
+
{
|
741 |
+
if (!class_exists('WP_Session_Tokens', false)) {
|
742 |
+
return null;
|
743 |
+
}
|
744 |
+
|
745 |
+
return WP_Session_Tokens::get_instance($userId);
|
746 |
+
}
|
747 |
}
|
src/MWP/WordPress/SessionStore.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* This file is part of the ManageWP Worker plugin.
|
4 |
+
*
|
5 |
+
* (c) ManageWP LLC <contact@managewp.com>
|
6 |
+
*
|
7 |
+
* For the full copyright and license information, please view the LICENSE
|
8 |
+
* file that was distributed with this source code.
|
9 |
+
*/
|
10 |
+
|
11 |
+
class MWP_WordPress_SessionStore
|
12 |
+
{
|
13 |
+
|
14 |
+
private $context;
|
15 |
+
|
16 |
+
private $sessionsKey = 'mwp_sessions';
|
17 |
+
|
18 |
+
public function __construct(MWP_WordPress_Context $context)
|
19 |
+
{
|
20 |
+
$this->context = $context;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param int $userId
|
25 |
+
* @param string $token
|
26 |
+
*/
|
27 |
+
public function add($userId, $token)
|
28 |
+
{
|
29 |
+
$sessions = $this->getSessions();
|
30 |
+
$sessions[(int) $userId][] = (string) $token;
|
31 |
+
|
32 |
+
$this->saveSessions($sessions);
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return int Number of destroyed sessions.
|
37 |
+
*/
|
38 |
+
public function destroyAll()
|
39 |
+
{
|
40 |
+
if (!$this->context->isVersionAtLeast('4.0.0')) {
|
41 |
+
// Not supported before WordPress 4.0.0.
|
42 |
+
return -1;
|
43 |
+
}
|
44 |
+
|
45 |
+
$removed = 0;
|
46 |
+
foreach ($this->getSessions() as $userId => $tokens) {
|
47 |
+
$sessionTokens = $this->context->getSessionTokens($userId);
|
48 |
+
foreach ($tokens as $token) {
|
49 |
+
$sessionTokens->destroy($token);
|
50 |
+
$removed++;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
$this->saveSessions(array());
|
55 |
+
|
56 |
+
return $removed;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Returns array of arrays of session IDs, indexed by user ID.
|
61 |
+
*
|
62 |
+
* @example
|
63 |
+
* -
|
64 |
+
* user_id_1:
|
65 |
+
* - token_id_1
|
66 |
+
* - token_id_2
|
67 |
+
* user_id_2:
|
68 |
+
* - token_id_3
|
69 |
+
* - token_id_4
|
70 |
+
* - token_id_5
|
71 |
+
* ...
|
72 |
+
*
|
73 |
+
* @return array[]
|
74 |
+
*/
|
75 |
+
private function getSessions()
|
76 |
+
{
|
77 |
+
$sessions = $this->context->transientGet($this->sessionsKey);
|
78 |
+
|
79 |
+
return $sessions ? $sessions : array();
|
80 |
+
}
|
81 |
+
|
82 |
+
private function saveSessions($sessions)
|
83 |
+
{
|
84 |
+
$this->context->transientSet($this->sessionsKey, $sessions);
|
85 |
+
}
|
86 |
+
}
|
src/MWP/Worker/Exception.php
CHANGED
@@ -31,9 +31,15 @@ class MWP_Worker_Exception extends Exception
|
|
31 |
const CONNECTION_PUBLIC_KEY_NOT_PROVIDED = 10021;
|
32 |
const CONNECTION_VERIFICATION_TEST_FAILED = 10022;
|
33 |
const PHP_EVAL_ERROR = 10023;
|
34 |
-
const LEGACY_AUTHENTICATION_INVALID_SIGNATURE =
|
35 |
-
const LEGACY_AUTHENTICATION_KEY_EXISTS =
|
36 |
-
const AUTO_LOGIN_USERNAME_REQUIRED =
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
const GENERAL_ERROR = 10000;
|
39 |
|
31 |
const CONNECTION_PUBLIC_KEY_NOT_PROVIDED = 10021;
|
32 |
const CONNECTION_VERIFICATION_TEST_FAILED = 10022;
|
33 |
const PHP_EVAL_ERROR = 10023;
|
34 |
+
const LEGACY_AUTHENTICATION_INVALID_SIGNATURE = 10024;
|
35 |
+
const LEGACY_AUTHENTICATION_KEY_EXISTS = 10025;
|
36 |
+
const AUTO_LOGIN_USERNAME_REQUIRED = 10026;
|
37 |
+
const FILESYSTEM_CREDENTIALS_ERROR = 10027;
|
38 |
+
const SHELL_NOT_AVAILABLE = 10028;
|
39 |
+
const BACKUP_DATABASE_METHOD_NOT_AVAILABLE = 10029;
|
40 |
+
const BACKUP_DATABASE_FAILED = 10030;
|
41 |
+
const BACKUP_DATABASE_MISSING_TABLES = 10031;
|
42 |
+
const IO_EXCEPTION = 10032;
|
43 |
|
44 |
const GENERAL_ERROR = 10000;
|
45 |
|
src/MWP/Worker/Kernel.php
CHANGED
@@ -96,7 +96,7 @@ class MWP_Worker_Kernel
|
|
96 |
}
|
97 |
|
98 |
// Allow listeners to modify action parameters.
|
99 |
-
$actionRequestEvent = new MWP_Event_ActionRequest($request, $params);
|
100 |
$this->dispatcher->dispatch(MWP_Event_Events::ACTION_REQUEST, $actionRequestEvent);
|
101 |
$params = $actionRequestEvent->getParams();
|
102 |
|
96 |
}
|
97 |
|
98 |
// Allow listeners to modify action parameters.
|
99 |
+
$actionRequestEvent = new MWP_Event_ActionRequest($request, $params, $actionDefinition);
|
100 |
$this->dispatcher->dispatch(MWP_Event_Events::ACTION_REQUEST, $actionRequestEvent);
|
101 |
$params = $actionRequestEvent->getParams();
|
102 |
|
src/MWP/Worker/Request.php
CHANGED
@@ -180,7 +180,7 @@ class MWP_Worker_Request
|
|
180 |
$this->attributes['data'] = $data;
|
181 |
$this->attributes['params'] = $data['params'];
|
182 |
$this->attributes['setting'] = array_key_exists('setting', $data) ? $data['setting'] : null;
|
183 |
-
$this->attributes['user'] = (
|
184 |
}
|
185 |
}
|
186 |
|
180 |
$this->attributes['data'] = $data;
|
181 |
$this->attributes['params'] = $data['params'];
|
182 |
$this->attributes['setting'] = array_key_exists('setting', $data) ? $data['setting'] : null;
|
183 |
+
$this->attributes['user'] = (isset($data['params']['username']) && is_scalar($data['params']['username'])) ? $data['params']['username'] : null;
|
184 |
}
|
185 |
}
|
186 |
|
src/Monolog/Formatter/LineFormatter.php
CHANGED
@@ -69,7 +69,7 @@ class Monolog_Formatter_LineFormatter extends Monolog_Formatter_NormalizerFormat
|
|
69 |
protected function normalizeException(Exception $e)
|
70 |
{
|
71 |
$previousText = '';
|
72 |
-
if ($previous = $e->getPrevious()) {
|
73 |
do {
|
74 |
$previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
|
75 |
} while ($previous = $previous->getPrevious());
|
69 |
protected function normalizeException(Exception $e)
|
70 |
{
|
71 |
$previousText = '';
|
72 |
+
if (is_callable(array($e, 'getPrevious')) && $previous = $e->getPrevious()) {
|
73 |
do {
|
74 |
$previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
|
75 |
} while ($previous = $previous->getPrevious());
|
version
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
-
4.0
|
2 |
-
2015-
|
1 |
+
4.1.0
|
2 |
+
2015-04-23 00:00:00
|