function mwp_autoload($class)
if (substr($class, 0, 8) === 'Symfony_'
|| substr($class, 0, 8) === 'Monolog_'
|| substr($class, 0, 5) === 'Gelf_'
|| substr($class, 0, 4) === 'MWP_'
|| substr($class, 0, 4) === 'MMB_'
$file = dirname(__FILE__).'/src/'.str_replace('_', '/', $class).'.php';
if (file_exists($file)) {
* @return Monolog_Psr_LoggerInterface
return mwp_container()->getLogger();
* @return MWP_WordPress_Context
return mwp_container()->getWordPressContext();
function mwp_worker_configuration()
return mwp_container()->getConfiguration();
function mwp_format_memory_limit($limit)
if ((string)(int)$limit === (string)$limit) {
// The number is numeric.
return mwp_format_bytes($limit);
$units = strtolower(substr($limit, -1));
if (!in_array($units, array('b', 'k', 'm', 'g'))) {
$number = substr($limit, 0, -1);
if ((string)(int)$number !== $number) {
// The number isn't numeric.
function mwp_format_bytes($bytes)
if ($bytes > 1024 * 1024 * 1024) {
return round($bytes / 1024 / 1024 / 1024, 2).' GB';
} elseif ($bytes > 1024 * 1024) {
return round($bytes / 1024 / 1024, 2).' MB';
} elseif ($bytes > 1024) {
return round($bytes / 1024, 2).' KB';
function cleanup_delete_worker($params = array())
$revision_params = get_option('mmb_stats_filter');
$revision_limit = isset($revision_params['plugins']['cleanup']['revisions']) ? str_replace('r_', '', $revision_params['plugins']['cleanup']['revisions']) : 5;
$params_array = explode('_', $params['actions']);
foreach ($params_array as $param) {
if (mmb_delete_all_revisions($revision_limit)) {
$return_array['revision'] = 'OK';
$return_array['revision_error'] = 'OK, nothing to do';
if (mmb_handle_overhead(true)) {
$return_array['overhead'] = 'OK';
$return_array['overhead_error'] = 'OK, nothing to do';
if (mmb_delete_spam_comments()) {
$return_array['comment'] = 'OK';
$return_array['comment_error'] = 'OK, nothing to do';
mmb_response($return_array, true);
function mmb_num_revisions($leaveRevsPerPost)
$query = "SELECT SUM(t.cnt) FROM (SELECT COUNT(ID) - {$leaveRevsPerPost} as cnt FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent != 0 GROUP BY post_parent HAVING COUNT(ID) > {$leaveRevsPerPost}) as t";
return $wpdb->get_var($query);
function mmb_delete_all_revisions($filter)
$num_rev = isset($filter['num_to_keep']) ? (int)str_replace("r_", "", $filter['num_to_keep']) : 5;
$allRevisions = $wpdb->get_results("SELECT post_parent FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent != 0 GROUP BY post_parent HAVING COUNT(ID) > {$num_rev}");
if (!is_array($allRevisions)) {
foreach ($allRevisions as $revision) {
$toKeep = $wpdb->get_results("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent = '{$revision->post_parent}' ORDER BY post_date DESC LIMIT ".$num_rev);
foreach ($toKeep as $keep) {
$keepArray[] = $keep->ID;
$keepQuery = implode(', ', $keepArray);
$wpdb->query("DELETE FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent = '{$revision->post_parent}' AND ID NOT IN ({$keepQuery})");
function mmb_handle_overhead($clear = false)
$query = 'SHOW TABLE STATUS';
$tables = $wpdb->get_results($query, ARRAY_A);
$tablesToOptimize = array();
foreach ($tables as $table) {
if (!isset($table['Engine']) || $table['Engine'] !== 'MyISAM' || $table['Data_free'] == 0) {
if ($wpdb->base_prefix === $wpdb->prefix && !preg_match('/^'.preg_quote($wpdb->prefix).'/Ui', $table['Name'])) {
if ($wpdb->base_prefix !== $wpdb->prefix && !preg_match('/^'.preg_quote($wpdb->prefix).'\d+_/Ui', $table['Name'])) {
$tableOverhead += $table['Data_free'] / 1024;
$tablesToOptimize[] = $table['Name'];
if (!$clear) { // we should only return the overhead
return round($tableOverhead, 3);
foreach ($tablesToOptimize as $tableToOptimize) {
$query = 'OPTIMIZE TABLE '.$tableToOptimize;
$optimize = ((bool)$wpdb->query($query)) && $optimize;
function mmb_num_spam_comments()
$sql = "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = 'spam'";
$num_spams = $wpdb->get_var($sql);
function mmb_delete_spam_comments()
$getCommentsQuery = "SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' LIMIT 1000";
$spam = $wpdb->get_results($getCommentsQuery);
foreach ($spam as $comment) {
$commentIds[] = $comment->comment_ID;
// Avoid queries to comments by caching the comment.
// Plugins which hook to 'delete_comment' might call get_comment($id), which in turn returns the cached version.
wp_cache_add($comment->comment_ID, $comment, 'comment');
do_action('delete_comment', $comment->comment_ID);
wp_cache_delete($comment->comment_ID, 'comment');
$commentIdsList = implode(', ', array_map('intval', $commentIds));
$wpdb->query("DELETE FROM {$wpdb->comments} WHERE comment_ID IN ($commentIdsList)");
$wpdb->query("DELETE FROM {$wpdb->commentmeta} WHERE comment_id IN ($commentIdsList)");
function mwp_is_nio_shell_available()
$process = new Symfony_Process_Process("cd .", dirname(__FILE__), array(), null, 1);
$check = $process->isSuccessful();
function mwp_is_shell_available()
if (mwp_container()->getParameter('disable_shell')) {
if (mwp_is_safe_mode()) {
if (!function_exists('proc_open') || !function_exists('escapeshellarg')) {
$neededFunction = array('proc_get_status', 'proc_open');
$disabledFunction = mwp_get_disabled_functions();
if (count(array_diff($neededFunction, $disabledFunction)) != count($neededFunction)) {
if (!mwp_is_nio_shell_available()) {
function mwp_get_disabled_functions()
$list = array_merge(explode(',', ini_get('disable_functions')), explode(',', ini_get('suhosin.executor.func.blacklist')));
$list = array_map('trim', $list);
$list = array_map('strtolower', $list);
$list = array_filter($list);
function mwp_is_safe_mode()
$value = ini_get("safe_mode");
if ((int)$value === 0 || strtolower($value) === "off") {
function mmb_response($response = false, $success = true)
if (!is_scalar($response)) {
$response = json_encode($response);
throw new MWP_Worker_Exception(MWP_Worker_Exception::GENERAL_ERROR, $response);
throw new MWP_Worker_ActionResponse($response);
function mmb_remove_site($params)
mwp_core()->deactivate(false, false);
mwp_remove_current_key();
'removed_data' => 'Site removed successfully. <br /><br /><b>ManageWP Worker plugin was not deactivated.</b>',
function mwp_get_stats(array $params)
mwp_context()->requireWpRewrite();
mwp_context()->requireTaxonomies();
mwp_context()->requirePostTypes();
mwp_context()->requireTheme();
mwp_logger()->debug('Starting get_stats after everything was required');
$return = mwp_core()->get_stats_instance()->get_stats($params);
function mmb_update_worker_plugin($params)
if (!empty($params['version'])) {
$recoveryKit = new MwpRecoveryKit();
update_option('mwp_incremental_update_active', time());
$files = $recoveryKit->recover($params['version']);
update_option('mwp_incremental_update_active', '');
update_option('mwp_incremental_update_active', '');
mmb_response(array('files' => $files, 'success' => 'ManageWP Worker plugin successfully updated'), true);
mmb_response(mwp_core()->update_worker_plugin($params), true);
function mmb_install_addon($params)
mwp_context()->requireTheme();
mwp_load_required_components();
$return = mwp_core()->get_installer_instance()->install_remote_file($params);
mmb_response($return, true);
function mmb_do_upgrade($params)
mwp_context()->requireTheme();
$return = mwp_core()->get_installer_instance()->do_upgrade($params);
mmb_response($return, true);
function mmb_bulk_action_comments($params)
$return = mwp_core()->get_comment_instance()->bulk_action_comments($params);
if (is_array($return) && array_key_exists('error', $return)) {
mmb_response($return['error'], false);
mmb_response($return, true);
function mmb_add_user($params)
$return = mwp_core()->get_user_instance()->add_user($params);
if (is_array($return) && array_key_exists('error', $return)) {
mmb_response($return['error'], false);
mmb_response($return, true);
function mmb_edit_users($params)
$users = mwp_core()->get_user_instance()->edit_users($params);
$response = 'User updated.';
foreach ($users as $username => $user) {
$check_error = is_array($user) && array_key_exists('error', $user);
$response = $username.': '.$user['error'];
mmb_response($response, !$check_error);
function mmb_iframe_plugins_fix($update_actions)
foreach ($update_actions as $key => $action) {
$update_actions[$key] = str_replace('target="_parent"', '', $action);
function mmb_execute_php_code($params)
$errorHandler = new MWP_Debug_EvalErrorHandler();
set_error_handler(array($errorHandler, 'handleError'));
if (!empty($params['code64'])) {
$params['code'] = base64_decode(substr($params['code64'], 2));
$returnValue = eval($params['code']); // This code handles the "Execute PHP Snippet" functionality on ManageWP and is not a security issue.
$errors = $errorHandler->getErrorMessages();
$return = array('output' => ob_get_clean(), 'returnValue' => $returnValue);
$return['errorLog'] = $errors;
$lastError = error_get_last();
if (($lastError !== null)
&& ($lastError['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))
&& (strpos($lastError['file'], __FILE__) !== false)
&& (strpos($lastError['file'], 'eval()') !== false)
$return['fatalError'] = $lastError;
mmb_response($return, true);
function mmb_upload_file_action($params)
$transactions = getUploadMessages();
if (!file_exists($params['file_path'])) {
mmb_response(array('message' => $transactions['path_not_exist'], 'ok' => false), true);
if (!is_writable($params['file_path'])) {
mmb_response(array('message' => $transactions['permissions_denied'], 'ok' => false), true);
$pathName = $params['file_path'];
if (substr($pathName, -1) !== '/') {
$pathName = $pathName.'/';
$filePath = $pathName.$params['file_name'];
if (file_exists($filePath) && !$params['overwrite']) {
mmb_response(array('message' => $transactions['file_exist'], 'ok' => false), true);
$file = fopen($filePath, 'w');
if (!fwrite($file, base64_decode($params['content']))) {
mmb_response(array('message' => $transactions['upload_failed'], 'ok' => false), true);
$isWritable = is_writable($filePath);
'fileName' => basename($filePath),
'date' => filemtime($filePath),
'permissions' => substr(sprintf('%o', fileperms($filePath)), -4),
'fileType' => pathinfo($filePath, PATHINFO_EXTENSION),