Initial commit: Atomaste website
This commit is contained in:
@@ -0,0 +1,440 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles Analytics Commands
|
||||
*
|
||||
* @method array ga_checker()
|
||||
* @method array get_access_token()
|
||||
* @method array set_authorization_code()
|
||||
*/
|
||||
class UpdraftCentral_Analytics_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
private $scope = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/analytics.readonly';
|
||||
|
||||
private $endpoint = 'https://accounts.google.com/o/oauth2/auth';
|
||||
|
||||
private $token_info_endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo';
|
||||
|
||||
private $access_key = 'updraftcentral_auth_server_access';
|
||||
|
||||
private $auth_endpoint;
|
||||
|
||||
private $client_id;
|
||||
|
||||
private $view_key = 'updraftcentral_analytics_views';
|
||||
|
||||
private $tracking_id_key = 'updraftcentral_analytics_tracking_id';
|
||||
|
||||
private $expiration;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->auth_endpoint = defined('UPDRAFTPLUS_GOOGLE_ANALYTICS_CALLBACK_URL') ? UPDRAFTPLUS_GOOGLE_ANALYTICS_CALLBACK_URL : 'https://auth.updraftplus.com/auth/googleanalytics';
|
||||
$this->client_id = defined('UPDRAFTPLUS_GOOGLE_ANALYTICS_CLIENT_ID') ? UPDRAFTPLUS_GOOGLE_ANALYTICS_CLIENT_ID : '306245874349-6s896c3tjpra26ns3dpplhqcl6rv6qlb.apps.googleusercontent.com';
|
||||
|
||||
// Set transient expiration - default for 24 hours
|
||||
$this->expiration = 86400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether Google Analytics (GA) is installed or setup
|
||||
*
|
||||
* N.B. This check assumes GA is installed either using "wp_head" or "wp_footer" (e.g. attached
|
||||
* to the <head/> or somewhere before </body>). It does not recursively check all the pages
|
||||
* of the website to find if GA is installed on each or one of those pages, but only on the main/root page.
|
||||
*
|
||||
* @return array $result An array containing "ga_installed" property which returns "true" if GA (Google Analytics) is installed, "false" otherwise.
|
||||
*/
|
||||
public function ga_checker() {
|
||||
|
||||
try {
|
||||
|
||||
// Retrieves the tracking code/id if available
|
||||
$tracking_id = $this->get_tracking_id();
|
||||
$installed = true;
|
||||
|
||||
// If tracking code/id is currently not available then we
|
||||
// parse the needed information from the buffered content through
|
||||
// the "wp_head" and "wp_footer" hooks.
|
||||
if (false === $tracking_id) {
|
||||
$info = $this->extract_tracking_id();
|
||||
|
||||
$installed = $info['installed'];
|
||||
$tracking_id = $info['tracking_id'];
|
||||
}
|
||||
|
||||
// Get access token to be use to generate the report.
|
||||
$access_token = $this->_get_token();
|
||||
|
||||
if (empty($access_token)) {
|
||||
// If we don't get a valid access token then that would mean
|
||||
// the access has been revoked by the user or UpdraftCentral was not authorized yet
|
||||
// to access the user's analytics data, thus, we're clearing
|
||||
// any previously stored user access so we're doing some housekeeping here.
|
||||
$this->clear_user_access();
|
||||
}
|
||||
|
||||
// Wrap and combined information for the requesting
|
||||
// client's consumption
|
||||
$result = array(
|
||||
'ga_installed' => $installed,
|
||||
'tracking_id' => $tracking_id,
|
||||
'client_id' => $this->client_id,
|
||||
'redirect_uri' => $this->auth_endpoint,
|
||||
'scope' => $this->scope,
|
||||
'access_token' => $access_token,
|
||||
'endpoint' => $this->endpoint
|
||||
);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts Google Tracking ID from contents rendered through the "wp_head" and "wp_footer" action hooks
|
||||
*
|
||||
* @internal
|
||||
* @return array $result An array containing the result of the extraction.
|
||||
*/
|
||||
private function extract_tracking_id() {
|
||||
|
||||
// Define result array
|
||||
$result = array();
|
||||
|
||||
// Retrieve header content
|
||||
ob_start();
|
||||
do_action('wp_head');
|
||||
$header_content = ob_get_clean();
|
||||
|
||||
// Extract analytics information if available.
|
||||
$output = $this->parse_content($header_content);
|
||||
$result['installed'] = $output['installed'];
|
||||
$result['tracking_id'] = $output['tracking_id'];
|
||||
|
||||
// If it was not found, then now try the footer
|
||||
if (empty($result['tracking_id'])) {
|
||||
// Retrieve footer content
|
||||
ob_start();
|
||||
do_action('wp_footer');
|
||||
$footer_content = ob_get_clean();
|
||||
$output = $this->parse_content($footer_content);
|
||||
$result['installed'] = $output['installed'];
|
||||
$result['tracking_id'] = $output['tracking_id'];
|
||||
}
|
||||
|
||||
if (!empty($result['tracking_id'])) {
|
||||
set_transient($this->tracking_id_key, $result['tracking_id'], $this->expiration);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets access token
|
||||
*
|
||||
* Validates whether the system currently have a valid token to use when connecting to Google Analytics API.
|
||||
* If not, then it will send a token request based on the authorization code we stored during the
|
||||
* authorization phase. Otherwise, it will return an empty token.
|
||||
*
|
||||
* @return array $result An array containing the Google Analytics API access token.
|
||||
*/
|
||||
public function get_access_token() {
|
||||
|
||||
try {
|
||||
|
||||
// Loads or request a valid token to use
|
||||
$access_token = $this->_get_token();
|
||||
|
||||
if (!empty($access_token)) {
|
||||
$result = array('access_token' => $access_token);
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'ga_token_retrieval_failed', 'values' => array());
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any previously stored user access
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear_user_access() {
|
||||
return delete_option($this->access_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves user is and access token received from the auth server
|
||||
*
|
||||
* @param array $query Parameter array containing the user id and access token from the auth server.
|
||||
* @return array $result An array containing a "success" or "failure" message as a result of the current process.
|
||||
*/
|
||||
public function save_user_access($query) {
|
||||
|
||||
try {
|
||||
|
||||
$token = get_option($this->access_key, false);
|
||||
$result = array();
|
||||
|
||||
if (false === $token) {
|
||||
$token = array(
|
||||
'user_id' => base64_decode(urldecode($query['user_id'])),
|
||||
'access_token' => base64_decode(urldecode($query['access_token']))
|
||||
);
|
||||
|
||||
if (false !== update_option($this->access_key, $token)) {
|
||||
$result = array('error' => false, 'message' => 'ga_access_saved', 'values' => array());
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'ga_access_saving_failed', 'values' => array($query['access_token']));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the tracking code/id manually (user input)
|
||||
*
|
||||
* @param array $query Parameter array containing the tracking code/id to save.
|
||||
* @return array $result An array containing the result of the process.
|
||||
*/
|
||||
public function save_tracking_id($query) {
|
||||
try {
|
||||
$tracking_id = $query['tracking_id'];
|
||||
$saved = false;
|
||||
|
||||
if (!empty($tracking_id)) {
|
||||
$saved = set_transient($this->tracking_id_key, $tracking_id, $this->expiration);
|
||||
}
|
||||
|
||||
$result = array('saved' => $saved);
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves any available access token either previously saved info or
|
||||
* from a new request from the Google Server.
|
||||
*
|
||||
* @internal
|
||||
* @return string $authorization_code
|
||||
*/
|
||||
private function _get_token() {
|
||||
|
||||
// Retrieves the tracking code/id if available
|
||||
$tracking_id = $this->get_tracking_id();
|
||||
$access_token = '';
|
||||
|
||||
$token = get_option($this->access_key, false);
|
||||
if (false !== $token) {
|
||||
$access_token = isset($token['access_token']) ? $token['access_token'] : '';
|
||||
$user_id = isset($token['user_id']) ? $token['user_id'] : '';
|
||||
|
||||
if ((!empty($access_token) && !$this->_token_valid($access_token)) || (!empty($user_id) && empty($access_token) && !empty($tracking_id))) {
|
||||
if (!empty($user_id)) {
|
||||
$args = array(
|
||||
'headers' => apply_filters('updraftplus_auth_headers', array())
|
||||
);
|
||||
|
||||
$response = wp_remote_get($this->auth_endpoint.'?user_id='.$user_id.'&code=ud_googleanalytics_code', $args);
|
||||
if (is_wp_error($response)) {
|
||||
throw new Exception($response->get_error_message()); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- The escaping should be happening when the exception is printed
|
||||
} else {
|
||||
if (is_array($response)) {
|
||||
|
||||
$body = json_decode($response['body'], true);
|
||||
$token_response = array();
|
||||
|
||||
if (is_array($body) && !isset($body['error'])) {
|
||||
$token_response = json_decode(base64_decode($body[0]), true);
|
||||
}
|
||||
|
||||
if (is_array($token_response) && isset($token_response['access_token'])) {
|
||||
$access_token = $token_response['access_token'];
|
||||
} else {
|
||||
// If we don't get any valid response then that would mean that the
|
||||
// permission was already revoked. Thus, we need to re-authorize the
|
||||
// user before using the analytics feature once again.
|
||||
$access_token = '';
|
||||
}
|
||||
|
||||
$token['access_token'] = $access_token;
|
||||
update_option($this->access_key, $token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $access_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies whether the access token is still valid for use
|
||||
*
|
||||
* @internal
|
||||
* @param string $token The access token to be check and validated
|
||||
* @return bool
|
||||
* @throws Exception If an error has occurred while connecting to the Google Server.
|
||||
*/
|
||||
private function _token_valid($token) {
|
||||
|
||||
$response = wp_remote_get($this->token_info_endpoint.'?access_token='.$token);
|
||||
if (is_wp_error($response)) {
|
||||
throw new Exception($response->get_error_message()); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- The escaping should be happening when the exception is printed
|
||||
} else {
|
||||
if (is_array($response)) {
|
||||
$response = json_decode($response['body'], true);
|
||||
if (!empty($response)) {
|
||||
if (!isset($response['error']) && !isset($response['error_description'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and extracts the google analytics information (NEEDED)
|
||||
*
|
||||
* @internal
|
||||
* @param string $content The content to parse
|
||||
* @return array An array containing the status of the process along with the tracking code/id
|
||||
*/
|
||||
private function parse_content($content) {
|
||||
|
||||
$installed = false;
|
||||
$gtm_installed = false;
|
||||
$tracking_id = '';
|
||||
$script_file_found = false;
|
||||
$tracking_id_found = false;
|
||||
|
||||
// Pull google analytics script file(s)
|
||||
preg_match_all('/<script\b[^>]*>([\s\S]*?)<\/script>/i', $content, $scripts);
|
||||
for ($i=0; $i < count($scripts[0]); $i++) {
|
||||
// Check for Google Analytics file
|
||||
if (stristr($scripts[0][$i], 'ga.js') || stristr($scripts[0][$i], 'analytics.js')) {
|
||||
$script_file_found = true;
|
||||
}
|
||||
|
||||
// Check for Google Tag Manager file
|
||||
// N.B. We are not checking for GTM but this check will be useful when
|
||||
// showing the notice to the user if we haven't found Google Analytics
|
||||
// directly being installed on the page.
|
||||
if (stristr($scripts[0][$i], 'gtm.js')) {
|
||||
$gtm_installed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Pull tracking code
|
||||
preg_match_all('/UA-[0-9]{5,}-[0-9]{1,}/i', $content, $codes);
|
||||
if (count($codes) > 0) {
|
||||
if (!empty($codes[0])) {
|
||||
$tracking_id_found = true;
|
||||
$tracking_id = $codes[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
// If we found both the script and the tracking code then it is safe
|
||||
// to say that Google Analytics (GA) is installed. Thus, we're returning
|
||||
// "true" as a response.
|
||||
if ($script_file_found && $tracking_id_found) {
|
||||
$installed = true;
|
||||
}
|
||||
|
||||
// Return result of process.
|
||||
return array(
|
||||
'installed' => $installed,
|
||||
'gtm_installed' => $gtm_installed,
|
||||
'tracking_id' => $tracking_id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the "analytics_tracking_id" transient
|
||||
*
|
||||
* @internal
|
||||
* @return mixed Returns the value of the saved transient. Returns "false" if the transient does not exist.
|
||||
*/
|
||||
private function get_tracking_id() {
|
||||
return get_transient($this->tracking_id_key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current tracking id
|
||||
*
|
||||
* @return array $result An array containing the Google Tracking ID.
|
||||
*/
|
||||
public function get_current_tracking_id() {
|
||||
try {
|
||||
|
||||
// Get current site transient stored for this key
|
||||
$tracking_id = get_transient($this->tracking_id_key);
|
||||
|
||||
// Checks whether we have a valid token
|
||||
$access_token = $this->_get_token();
|
||||
if (empty($access_token)) {
|
||||
$tracking_id = '';
|
||||
}
|
||||
|
||||
if (false === $tracking_id) {
|
||||
$result = $this->extract_tracking_id();
|
||||
} else {
|
||||
$result = array(
|
||||
'installed' => true,
|
||||
'tracking_id' => $tracking_id
|
||||
);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears user access from database
|
||||
*
|
||||
* @return array $result An array containing the "Remove" confirmation whether the action succeeded or not.
|
||||
*/
|
||||
public function remove_user_access() {
|
||||
try {
|
||||
|
||||
// Clear user access
|
||||
$is_cleared = $this->clear_user_access();
|
||||
|
||||
if (false !== $is_cleared) {
|
||||
$result = array('removed' => true);
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'user_access_remove_failed', 'values' => array());
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => 'generic_response_error', 'values' => array($e->getMessage()));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles Backups Commands
|
||||
*/
|
||||
class UpdraftCentral_Backups_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
private $switched = false;
|
||||
|
||||
/**
|
||||
* Function that gets called before every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _pre_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- This function is called from listener.php and $extra_info is being sent.
|
||||
// Here we assign the current blog_id to a variable $blog_id
|
||||
$blog_id = get_current_blog_id();
|
||||
if (!empty($data['site_id'])) $blog_id = $data['site_id'];
|
||||
|
||||
if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
|
||||
$this->switched = switch_to_blog($blog_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that gets called after every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _post_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Unused parameter is present because the caller from UpdraftCentral_Listener class uses 3 arguments.
|
||||
// Here, we're restoring to the current (default) blog before we switched
|
||||
if ($this->switched) restore_current_blog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the UpdraftPlus plugin status, UpdraftVault storage usage status, Next backup
|
||||
* schedule, etc. Used primarily by UpdraftCentral background process.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_status() {
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
$response = array(
|
||||
'status' => 'error',
|
||||
'error_code' => 'insufficient_permission',
|
||||
);
|
||||
} else {
|
||||
|
||||
if (!function_exists('get_mu_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
|
||||
$mu_plugins = get_mu_plugins();
|
||||
|
||||
$is_premium = false;
|
||||
if (defined('UPDRAFTPLUS_DIR') && file_exists(UPDRAFTPLUS_DIR.'/udaddons')) $is_premium = true;
|
||||
|
||||
// Set default response
|
||||
$response = array(
|
||||
'updraftplus_version' => '',
|
||||
'is_premium' => $is_premium,
|
||||
'installed' => false,
|
||||
'active' => false,
|
||||
'backup_count' => 0,
|
||||
'has_mu_plugins' => !empty($mu_plugins) ? true : false,
|
||||
'last_backup' => array(
|
||||
'backup_nonce' => '',
|
||||
'has_errors' => false,
|
||||
'has_warnings' => false,
|
||||
'has_succeeded' => false,
|
||||
),
|
||||
'updraftvault' => array(
|
||||
'site_connected' => false,
|
||||
'storage' => array('quota_used' => '0 MB', 'quota' => '0 MB', 'percentage_usage' => '0.0%'),
|
||||
),
|
||||
'meta' => array(),
|
||||
);
|
||||
|
||||
if (class_exists('UpdraftPlus')) {
|
||||
global $updraftplus;
|
||||
|
||||
$response['updraftplus_version'] = $updraftplus->version;
|
||||
$response['updraftvault'] = $this->get_updraftvault_status();
|
||||
$response['installed'] = true;
|
||||
$response['active'] = true;
|
||||
$response['meta'] = $this->get_filesystem_credentials_info();
|
||||
|
||||
$schedule = $this->get_next_backup_schedule();
|
||||
if ($schedule) {
|
||||
$response['next_backup_schedule'] = $schedule;
|
||||
}
|
||||
|
||||
$backup_history = UpdraftPlus_Backup_History::add_jobdata(UpdraftPlus_Backup_History::get_history());
|
||||
|
||||
$response['backup_count'] = count($backup_history);
|
||||
|
||||
$updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
|
||||
if ($updraft_last_backup) {
|
||||
$response['last_backup']['backup_nonce'] = $updraft_last_backup['backup_nonce'];
|
||||
if (isset($updraft_last_backup['backup_time'])) {
|
||||
$response['last_backup']['backup_date'] = gmdate('n/j/Y', $updraft_last_backup['backup_time']);
|
||||
}
|
||||
|
||||
$errors = 0;
|
||||
$warnings = 0;
|
||||
|
||||
if (is_array($updraft_last_backup['errors'])) {
|
||||
foreach ($updraft_last_backup['errors'] as $err) {
|
||||
$level = (is_array($err)) ? $err['level'] : 'error';
|
||||
if ('warning' == $level) {
|
||||
$warnings++;
|
||||
} elseif ('error' == $level) {
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors > 0) $response['last_backup']['has_errors'] = true;
|
||||
if ($warnings > 0) $response['last_backup']['has_warnings'] = true;
|
||||
if (isset($updraft_last_backup['success']) && $updraft_last_backup['success']) $response['last_backup']['has_succeeded'] = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!function_exists('get_plugins')) require_once(ABSPATH.'wp-admin/includes/plugin.php');
|
||||
$plugins = get_plugins();
|
||||
$key = 'updraftplus/updraftplus.php';
|
||||
|
||||
if (array_key_exists($key, $plugins)) {
|
||||
$response['installed'] = true;
|
||||
if (is_plugin_active($key)) $response['active'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_response($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the next backup schedule for Files and Database backups
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_next_backup_schedule() {
|
||||
|
||||
// Get the next (nearest) scheduled backups
|
||||
$files = wp_next_scheduled('updraft_backup');
|
||||
$db = wp_next_scheduled('updraft_backup_database');
|
||||
|
||||
if ($files && $db) {
|
||||
$timestamp = min($files, $db); // Get the nearest schedule among the two schedules
|
||||
} elseif ($files && !$db) {
|
||||
$timestamp = $files;
|
||||
} elseif (!$files && $db) {
|
||||
$timestamp = $db;
|
||||
} else {
|
||||
$timestamp = null;
|
||||
}
|
||||
|
||||
if (!empty($timestamp)) {
|
||||
return gmdate('g:i A - D', $timestamp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the UpdrafVault storage usage status
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_updraftvault_status() {
|
||||
|
||||
if (!class_exists('UpdraftCentral_UpdraftVault_Commands')) {
|
||||
include_once(UPDRAFTPLUS_DIR.'/includes/updraftvault.php');
|
||||
}
|
||||
|
||||
$updraftvault = new UpdraftCentral_UpdraftVault_Commands($this->rc);
|
||||
$creds = $updraftvault->get_credentials();
|
||||
|
||||
$site_connected = false;
|
||||
$storage = array('quota_used' => '0 MB', 'quota' => '0 MB', 'percentage_usage' => '0.0%');
|
||||
$remote_service = false;
|
||||
|
||||
if (isset($creds['data'])) {
|
||||
if (!isset($creds['data']['error']) && isset($creds['data']['accesskey'])) {
|
||||
$site_connected = true;
|
||||
|
||||
$storage_objects_and_ids = UpdraftPlus_Storage_Methods_Interface::get_storage_objects_and_ids(array('updraftvault'));
|
||||
|
||||
if (isset($storage_objects_and_ids['updraftvault']['instance_settings'])) {
|
||||
$instance_settings = $storage_objects_and_ids['updraftvault']['instance_settings'];
|
||||
$instance_id = key($instance_settings);
|
||||
$opts = $instance_settings[$instance_id];
|
||||
|
||||
if (!class_exists('UpdraftPlus_BackupModule_updraftvault')) {
|
||||
include_once(UPDRAFTPLUS_DIR.'/methods/updraftvault.php');
|
||||
}
|
||||
|
||||
$vault = new UpdraftPlus_BackupModule_updraftvault();
|
||||
$vault->set_options($opts, false, $instance_id);
|
||||
|
||||
$quota_root = $opts['quota_root'];
|
||||
$quota = $opts['quota'];
|
||||
|
||||
if (empty($quota_root)) {
|
||||
// This next line is wrong: it lists the files *in this site's sub-folder*, rather than the whole Vault
|
||||
$current_files = $vault->listfiles('');
|
||||
} else {
|
||||
$current_files = $vault->listfiles_with_path($quota_root, '', true);
|
||||
}
|
||||
|
||||
if (!is_wp_error($current_files) && is_array($current_files)) {
|
||||
$quota_used = 0;
|
||||
foreach ($current_files as $file) {
|
||||
$quota_used += $file['size'];
|
||||
}
|
||||
|
||||
$storage = array(
|
||||
'quota_used' => round($quota_used / 1048576, 1).' MB',
|
||||
'quota' => round($quota / 1048576, 1).' MB',
|
||||
'percentage_usage' => sprintf('%.1f', 100*$quota_used / $quota).'%',
|
||||
);
|
||||
|
||||
$remote_service = array(
|
||||
'name' => 'updraft_include_remote_service_updraftvault',
|
||||
'value' => $instance_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'site_connected' => $site_connected,
|
||||
'storage' => $storage,
|
||||
'remote_service' => $remote_service,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information whether filesystem credentials (e.g. FTP/SSH) are required
|
||||
* when updating plugins
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_filesystem_credentials_info() {
|
||||
|
||||
if (!function_exists('get_filesystem_method')) {
|
||||
include_once(ABSPATH.'/wp-admin/includes/file.php');
|
||||
}
|
||||
|
||||
$filesystem_method = get_filesystem_method(array(), WP_PLUGIN_DIR);
|
||||
|
||||
ob_start();
|
||||
$filesystem_credentials_are_stored = request_filesystem_credentials(site_url());
|
||||
$filesystem_form = strip_tags(ob_get_contents(), '<div><h2><p><input><label><fieldset><legend><span><em>');
|
||||
ob_end_clean();
|
||||
|
||||
$request_filesystem_credentials = ('direct' != $filesystem_method && !$filesystem_credentials_are_stored);
|
||||
|
||||
return array(
|
||||
'request_filesystem_credentials' => $request_filesystem_credentials,
|
||||
'filesystem_form' => base64_encode($filesystem_form),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the backup progress in terms of entities completed. Used primarily by UpdraftCentral
|
||||
* for polling backup progress in the background.
|
||||
*
|
||||
* @param array $params Submitted arguments for the current request
|
||||
* @return array
|
||||
*/
|
||||
public function get_backup_progress($params) {
|
||||
|
||||
$nonce = isset($params['nonce']) ? $params['nonce'] : false;
|
||||
$response = array('nonce' => $params['nonce']);
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
$response['status'] = 'error';
|
||||
$response['error_code'] = 'insufficient_permission';
|
||||
} else {
|
||||
global $updraftplus;
|
||||
|
||||
if ($nonce && $updraftplus && is_a($updraftplus, 'UpdraftPlus')) {
|
||||
|
||||
// Check the job is not still running.
|
||||
$jobdata = $updraftplus->jobdata_getarray($nonce);
|
||||
|
||||
$response['status'] = 'idle'; // It's very rare to receive this in the UI as status. If it happens then that would mean that no backup has been done for the given nonce even if we initially received it from the "backupnow" request. Possible cause would be, is that the server is too busy or something happened in between calls.
|
||||
|
||||
if (!empty($jobdata)) {
|
||||
$response['status'] = 'in-progress';
|
||||
|
||||
$file_entities = 0;
|
||||
$db_entities = 0;
|
||||
$processed = 0;
|
||||
|
||||
if (isset($jobdata['backup_database']) && 'no' != $jobdata['backup_database']) {
|
||||
$backup_database = $jobdata['backup_database'];
|
||||
$db_entities += count($backup_database);
|
||||
|
||||
foreach ($backup_database as $whichdb => $info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- In this check we only need the status contained in the $info for now.
|
||||
$status = $info; // For default: 'wp'
|
||||
if (is_array($info)) {
|
||||
$status = $info['status'];
|
||||
}
|
||||
|
||||
if ('finished' == $status) {
|
||||
$processed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($jobdata['backup_files']) && 'no' != $jobdata['backup_files']) {
|
||||
$file_entities = count($jobdata['job_file_entities']);
|
||||
|
||||
$backup_files = $jobdata['backup_files'];
|
||||
if ('finished' == $backup_files) {
|
||||
$processed += $file_entities;
|
||||
} elseif (isset($jobdata['filecreating_substatus'])) {
|
||||
$substatus = $jobdata['filecreating_substatus'];
|
||||
$processed += max(0, intval($substatus['i']) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
$response['progress'] = array(
|
||||
'file_entities' => $file_entities,
|
||||
'db_entities' => $db_entities,
|
||||
'total_entities' => $file_entities+$db_entities,
|
||||
'processed' => $processed,
|
||||
'percentage' => floor(($processed/($file_entities+$db_entities))*100),
|
||||
'nonce' => $nonce,
|
||||
);
|
||||
|
||||
UpdraftPlus_Options::update_updraft_option('updraft_last_backup_progress', $response['progress'], false);
|
||||
} else {
|
||||
$last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
|
||||
if ($nonce == $last_backup['backup_nonce']) {
|
||||
$response['status'] = 'finished';
|
||||
$response['progress'] = array('percentage' => 100);
|
||||
$response['progress']['errors'] = $last_backup['errors'];
|
||||
|
||||
$errors = 0;
|
||||
$warnings = 0;
|
||||
|
||||
if (!empty($last_backup['errors']) && is_array($last_backup['errors'])) {
|
||||
foreach ($last_backup['errors'] as $err) {
|
||||
$level = (is_array($err)) ? $err['level'] : 'error';
|
||||
if ('warning' == $level) {
|
||||
$warnings++;
|
||||
} elseif ('error' == $level) {
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response['progress']['has_errors'] = ($errors > 0) ? true : false;
|
||||
$response['progress']['has_warnings'] = ($warnings > 0) ? true : false;
|
||||
} else {
|
||||
// We might be too early to check the `updraft_last_backup` thus, we'll
|
||||
// give it a few rounds to check by setting the status to "in-progress"
|
||||
// and returning the last backup progress.
|
||||
$last_progress = UpdraftPlus_Options::get_updraft_option('updraft_last_backup_progress');
|
||||
if ($nonce == $last_progress['nonce']) {
|
||||
$response['status'] = 'in-progress';
|
||||
$response['progress'] = $last_progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_response($response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,842 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
/**
|
||||
* The _search_comments function searches all available comments based
|
||||
* on the following query parameters (type, status, search)
|
||||
*
|
||||
* Search Parameters/Filters:
|
||||
* type - comment types can be 'comment', 'trackback' and 'pingback', defaults to 'comment'
|
||||
* status - comment status can be 'hold' or unapprove, 'approve', 'spam', 'trash'
|
||||
* search - user generated content or keyword
|
||||
*
|
||||
* @param array $query The query to search comments
|
||||
* @return array
|
||||
*/
|
||||
private function _search_comments($query) {
|
||||
|
||||
// Basic parameters to the query and should display
|
||||
// the results in descending order (latest comments) first
|
||||
// based on their generated IDs
|
||||
|
||||
$args = array(
|
||||
'orderby' => 'ID',
|
||||
'order' => 'DESC',
|
||||
'type' => $query['type'],
|
||||
'status' => $query['status'],
|
||||
'search' => esc_attr($query['search']),
|
||||
);
|
||||
|
||||
$query = new WP_Comment_Query;
|
||||
$found_comments = $query->query($args);
|
||||
|
||||
$comments = array();
|
||||
foreach ($found_comments as $comment) {
|
||||
|
||||
// We're returning a collection of comment in an array,
|
||||
// in sync with the originator of the request on the ui side
|
||||
// so, we're pulling it one by one into the array before
|
||||
// returning it.
|
||||
|
||||
if (!in_array($comment, $comments)) {
|
||||
array_push($comments, $comment);
|
||||
}
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* The _calculate_pages function generates and builds the pagination links
|
||||
* based on the current search parameters/filters. Please see _search_comments
|
||||
* for the breakdown of these parameters.
|
||||
*
|
||||
* @param array $query Query to generate pagination links
|
||||
* @return array
|
||||
*/
|
||||
private function _calculate_pages($query) {
|
||||
$per_page_options = array(10, 20, 30, 40, 50);
|
||||
|
||||
if (!empty($query)) {
|
||||
if (!empty($query['search'])) {
|
||||
return array(
|
||||
'page_count' => 1,
|
||||
'page_no' => 1
|
||||
);
|
||||
}
|
||||
|
||||
$pages = array();
|
||||
$page_query = new WP_Comment_Query;
|
||||
|
||||
// Here, we're pulling the comments based on the
|
||||
// two parameters namely type and status.
|
||||
//
|
||||
// The number of results/comments found will then
|
||||
// be use to compute for the number of pages to be
|
||||
// displayed as navigation links when browsing all
|
||||
// comments from the frontend.
|
||||
|
||||
$comments = $page_query->query(array(
|
||||
'type' => $query['type'],
|
||||
'status' => $query['status']
|
||||
));
|
||||
|
||||
$total_comments = count($comments);
|
||||
$page_count = ceil($total_comments / $query['per_page']);
|
||||
|
||||
if ($page_count > 1) {
|
||||
for ($i = 0; $i < $page_count; $i++) {
|
||||
if ($i + 1 == $query['page_no']) {
|
||||
$paginator_item = array(
|
||||
'value' => $i+1,
|
||||
'setting' => 'disabled'
|
||||
);
|
||||
} else {
|
||||
$paginator_item = array(
|
||||
'value' => $i+1
|
||||
);
|
||||
}
|
||||
array_push($pages, $paginator_item);
|
||||
}
|
||||
|
||||
if ($query['page_no'] >= $page_count) {
|
||||
$page_next = array(
|
||||
'value' => $page_count,
|
||||
'setting' => 'disabled'
|
||||
);
|
||||
} else {
|
||||
$page_next = array(
|
||||
'value' => $query['page_no'] + 1
|
||||
);
|
||||
}
|
||||
|
||||
if (1 === $query['page_no']) {
|
||||
$page_prev = array(
|
||||
'value' => 1,
|
||||
'setting' => 'disabled'
|
||||
);
|
||||
} else {
|
||||
$page_prev = array(
|
||||
'value' => $query['page_no'] - 1
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'page_no' => $query['page_no'],
|
||||
'per_page' => $query['per_page'],
|
||||
'page_count' => $page_count,
|
||||
'pages' => $pages,
|
||||
'page_next' => $page_next,
|
||||
'page_prev' => $page_prev,
|
||||
'total_results' => $total_comments,
|
||||
'per_page_options' => $per_page_options
|
||||
);
|
||||
|
||||
} else {
|
||||
return array(
|
||||
'page_no' => $query['page_no'],
|
||||
'per_page' => $query['per_page'],
|
||||
'page_count' => $page_count,
|
||||
'total_results' => $total_comments,
|
||||
'per_page_options' => $per_page_options
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return array(
|
||||
'per_page_options' => $per_page_options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_blog_sites function pulls blog sites available for the current WP instance.
|
||||
* If Multisite is enabled on the server, then sites under the network will be pulled, otherwise, it will return an empty array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_blog_sites() {
|
||||
|
||||
if (!is_multisite()) return array();
|
||||
|
||||
// Initialize array container
|
||||
$sites = $network_sites = array();
|
||||
|
||||
// Check to see if latest get_sites (available on WP version >= 4.6) function is
|
||||
// available to pull any available sites from the current WP instance. If not, then
|
||||
// we're going to use the fallback function wp_get_sites (for older version).
|
||||
|
||||
if (function_exists('get_sites') && class_exists('WP_Site_Query')) {
|
||||
$network_sites = get_sites();
|
||||
} else {
|
||||
if (function_exists('wp_get_sites')) {
|
||||
$network_sites = wp_get_sites();
|
||||
}
|
||||
}
|
||||
|
||||
// We only process if sites array is not empty, otherwise, bypass
|
||||
// the next block.
|
||||
|
||||
if (!empty($network_sites)) {
|
||||
foreach ($network_sites as $site) {
|
||||
|
||||
// Here we're checking if the site type is an array, because
|
||||
// we're pulling the blog_id property based on the type of
|
||||
// site returned.
|
||||
// get_sites returns an array of object, whereas the wp_get_sites
|
||||
// function returns an array of array.
|
||||
|
||||
$blog_id = (is_array($site)) ? $site['blog_id'] : $site->blog_id;
|
||||
|
||||
|
||||
// We're saving the blog_id and blog name as an associative item
|
||||
// into the sites array, that will be used as "Sites" option in
|
||||
// the frontend.
|
||||
|
||||
$sites[$blog_id] = get_blog_details($blog_id)->blogname;
|
||||
}
|
||||
}
|
||||
|
||||
return $sites;
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_wp_option function pulls current blog options
|
||||
* from the database using either following functions:
|
||||
* - get_blog_option (for multisite)
|
||||
* - get_option (for ordinary blog)
|
||||
*
|
||||
* @param array $blog_id This is the specific blog ID
|
||||
* @param array $setting specifies settings
|
||||
* @return array
|
||||
*/
|
||||
private function _get_wp_option($blog_id, $setting) {
|
||||
return is_multisite() ? get_blog_option($blog_id, $setting) : get_option($setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_comments function pull all the comments from the database
|
||||
* based on the current search parameters/filters. Please see _search_comments
|
||||
* for the breakdown of these parameters.
|
||||
*
|
||||
* @param array $query Specific query to pull comments
|
||||
* @return array
|
||||
*/
|
||||
public function get_comments($query) {
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($query['blog_id'])) $blog_id = $query['blog_id'];
|
||||
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull comments from.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
if (!empty($query['search'])) {
|
||||
// If a search keyword is present, then we'll call the _search_comments
|
||||
// function to process the query.
|
||||
|
||||
$comments = $this->_search_comments($query);
|
||||
} else {
|
||||
// Set default parameter values if the designated
|
||||
// parameters are empty.
|
||||
|
||||
if (empty($query['per_page'])) {
|
||||
$query['per_page'] = 10;
|
||||
}
|
||||
if (empty($query['page_no'])) {
|
||||
$query['page_no'] = 1;
|
||||
}
|
||||
if (empty($query['type'])) {
|
||||
$query['type'] = '';
|
||||
}
|
||||
if (empty($query['status'])) {
|
||||
$query['status'] = '';
|
||||
}
|
||||
|
||||
// Since WP_Comment_Query parameters doesn't have a "page" attribute, we
|
||||
// need to compute for the offset to get the exact content based on the
|
||||
// current page and the number of items per page.
|
||||
|
||||
$offset = ((int) $query['page_no'] - 1) * (int) $query['per_page'];
|
||||
$args = array(
|
||||
'orderby' => 'ID',
|
||||
'order' => 'DESC',
|
||||
'number' => $query['per_page'],
|
||||
'offset' => $offset,
|
||||
'type' => $query['type'],
|
||||
'status' => $query['status']
|
||||
);
|
||||
|
||||
$comments_query = new WP_Comment_Query;
|
||||
$comments = $comments_query->query($args);
|
||||
}
|
||||
|
||||
// If no comments are found based on the current query then
|
||||
// we return with error.
|
||||
|
||||
if (empty($comments)) {
|
||||
$result = array('message' => 'comments_not_found');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Otherwise, we're going to process each comment
|
||||
// before we return it to the one issuing the request.
|
||||
//
|
||||
// Process in the sense that we add additional related info
|
||||
// such as the post tile where the comment belongs to, the
|
||||
// comment status, a formatted date field, and to which parent comment
|
||||
// does the comment was intended to be as a reply.
|
||||
|
||||
foreach ($comments as &$comment) {
|
||||
$comment = get_comment($comment->comment_ID, ARRAY_A);
|
||||
if ($comment) {
|
||||
$post = get_post($comment['comment_post_ID']);
|
||||
|
||||
if ($post) $comment['in_response_to'] = $post->post_title;
|
||||
if (!empty($comment['comment_parent'])) {
|
||||
$parent_comment = get_comment($comment['comment_parent'], ARRAY_A);
|
||||
if ($parent_comment) $comment['in_reply_to'] = $parent_comment['comment_author'];
|
||||
}
|
||||
|
||||
// We're formatting the comment_date to be exactly the same
|
||||
// with that of WP Comments table (e.g. 2016/12/21 at 10:30 PM)
|
||||
|
||||
$comment['comment_date'] = date('Y/m/d \a\t g:i a', strtotime($comment['comment_date']));
|
||||
|
||||
$status = wp_get_comment_status($comment['comment_ID']);
|
||||
if ($status) {
|
||||
$comment['comment_status'] = $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We return the following to the one issuing
|
||||
// the request.
|
||||
|
||||
$result = array(
|
||||
'comments' => $comments,
|
||||
'paging' => $this->_calculate_pages($query)
|
||||
);
|
||||
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_comment_filters function builds a array of options
|
||||
* to be use as filters for the search function on the frontend.
|
||||
*/
|
||||
public function get_comment_filters() {
|
||||
// Options for comment_types field
|
||||
$comment_types = apply_filters('admin_comment_types_dropdown', array(
|
||||
'comment' => __('Comments'),// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core.
|
||||
'pings' => __('Pings'),// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core.
|
||||
));
|
||||
|
||||
// Options for comment_status field
|
||||
$comment_statuses = array(
|
||||
'approve' => __('Approve'),// phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- The string exists within the WordPress core.
|
||||
'hold' => __('Hold or Unapprove', 'updraftplus'),
|
||||
'trash' => __('Trash', 'updraftplus'),
|
||||
'spam' => __('Spam', 'updraftplus'),
|
||||
);
|
||||
|
||||
// Pull sites options if available.
|
||||
$sites = $this->get_blog_sites();
|
||||
|
||||
$result = array(
|
||||
'sites' => $sites,
|
||||
'types' => $comment_types,
|
||||
'statuses' => $comment_statuses,
|
||||
'paging' => $this->_calculate_pages(null),
|
||||
);
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_settings function pulls the current discussion settings
|
||||
* option values.
|
||||
*
|
||||
* @param array $params Passing specific params for getting current discussion settings
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings($params) {
|
||||
global $updraftcentral_main;
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to manage and edit
|
||||
// WP options then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'manage_options')) {
|
||||
$result = array('error' => true, 'message' => 'insufficient_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Pull sites options if available.
|
||||
$sites = $this->get_blog_sites();
|
||||
|
||||
// Wrap current discussion settings values into an array item
|
||||
// named settings.
|
||||
|
||||
$result = array(
|
||||
'settings' => array(
|
||||
'default_pingback_flag' => $this->_get_wp_option($blog_id, 'default_pingback_flag'),
|
||||
'default_ping_status' => $this->_get_wp_option($blog_id, 'default_ping_status'),
|
||||
'default_comment_status' => $this->_get_wp_option($blog_id, 'default_comment_status'),
|
||||
'require_name_email' => $this->_get_wp_option($blog_id, 'require_name_email'),
|
||||
'comment_registration' => $this->_get_wp_option($blog_id, 'comment_registration'),
|
||||
'close_comments_for_old_posts' => $this->_get_wp_option($blog_id, 'close_comments_for_old_posts'),
|
||||
'close_comments_days_old' => $this->_get_wp_option($blog_id, 'close_comments_days_old'),
|
||||
'thread_comments' => $this->_get_wp_option($blog_id, 'thread_comments'),
|
||||
'thread_comments_depth' => $this->_get_wp_option($blog_id, 'thread_comments_depth'),
|
||||
'page_comments' => $this->_get_wp_option($blog_id, 'page_comments'),
|
||||
'comments_per_page' => $this->_get_wp_option($blog_id, 'comments_per_page'),
|
||||
'default_comments_page' => $this->_get_wp_option($blog_id, 'default_comments_page'),
|
||||
'comment_order' => $this->_get_wp_option($blog_id, 'comment_order'),
|
||||
'comments_notify' => $this->_get_wp_option($blog_id, 'comments_notify'),
|
||||
'moderation_notify' => $this->_get_wp_option($blog_id, 'moderation_notify'),
|
||||
'comment_moderation' => $this->_get_wp_option($blog_id, 'comment_moderation'),
|
||||
'comment_max_links' => $this->_get_wp_option($blog_id, 'comment_max_links'),
|
||||
'moderation_keys' => $this->_get_wp_option($blog_id, 'moderation_keys'),
|
||||
),
|
||||
'sites' => $sites,
|
||||
);
|
||||
|
||||
$wp_version = $updraftcentral_main->get_wordpress_version();
|
||||
if (version_compare($wp_version, '5.5.0', '<')) {
|
||||
$result['settings']['comment_whitelist'] = $this->_get_wp_option($blog_id, 'comment_whitelist');
|
||||
$result['settings']['blacklist_keys'] = $this->_get_wp_option($blog_id, 'blacklist_keys');
|
||||
} else {
|
||||
$result['settings']['comment_previously_approved'] = $this->_get_wp_option($blog_id, 'comment_previously_approved');
|
||||
$result['settings']['disallowed_keys'] = $this->_get_wp_option($blog_id, 'disallowed_keys');
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The update_settings function updates the discussion settings
|
||||
* basing on the user generated content/option from the frontend
|
||||
* form.
|
||||
*
|
||||
* @param array $params Specific params to update settings based on discussion
|
||||
* @return array
|
||||
*/
|
||||
public function update_settings($params) {
|
||||
|
||||
// Extract settings values from passed parameters.
|
||||
$settings = $params['settings'];
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to manage and edit
|
||||
// WP options then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'manage_options')) {
|
||||
$result = array('error' => true, 'message' => 'insufficient_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're sanitizing the input fields before we save them to the database
|
||||
// for safety and security reason. The "explode" and "implode" functions are meant
|
||||
// to maintain the line breaks associated with a textarea input/value.
|
||||
|
||||
foreach ($settings as $key => $value) {
|
||||
|
||||
// We're using update_blog_option and update_option altogether to update the current
|
||||
// discussion settings.
|
||||
|
||||
if (is_multisite()) {
|
||||
update_blog_option($blog_id, $key, implode("\n", array_map('sanitize_text_field', explode("\n", $value))));
|
||||
} else {
|
||||
update_option($key, implode("\n", array_map('sanitize_text_field', explode("\n", $value))));
|
||||
}
|
||||
}
|
||||
|
||||
// We're not checking for errors here, but instead we're directly returning a success (error = false)
|
||||
// status always, because WP's update_option will return fail if values were not changed, meaning
|
||||
// previous values were not changed by the user's current request, not an actual exception thrown.
|
||||
// Thus, giving a false positive message or report to the frontend.
|
||||
|
||||
$result = array('error' => false, 'message' => 'settings_updated', 'values' => array());
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_comment function pulls a single comment based
|
||||
* on a comment ID.
|
||||
*
|
||||
* @param array $params Specific params for getting a single comment
|
||||
* @return array
|
||||
*/
|
||||
public function get_comment($params) {
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to moderate or edit
|
||||
// a comment then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
|
||||
$result = array('error' => true, 'message' => 'insufficient_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull comments from.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
// Get comment by comment_ID parameter and return result as an array.
|
||||
$result = array(
|
||||
'comment' => get_comment($params['comment_id'], ARRAY_A)
|
||||
);
|
||||
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The reply_comment function creates a new comment as a reply
|
||||
* to a certain/selected comment.
|
||||
*
|
||||
* @param array $params Specific params to create a new comment reply
|
||||
* @return array
|
||||
*/
|
||||
public function reply_comment($params) {
|
||||
|
||||
// Extract reply info from the passed parameters
|
||||
$reply = $params['comment'];
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to moderate or edit
|
||||
// a comment then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
|
||||
$result = array('error' => true, 'message' => 'comment_reply_no_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to apply our changes.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
|
||||
// Get comment by comment_ID parameter.
|
||||
$comment = get_comment($reply['comment_id']);
|
||||
if ($comment) {
|
||||
|
||||
// Get the currently logged in user
|
||||
$user = wp_get_current_user();
|
||||
|
||||
// If the current comment was not approved yet then
|
||||
// we need to approve it before we create a reply to
|
||||
// to the comment, mimicking exactly the WP behaviour
|
||||
// in terms of creating a reply to a comment.
|
||||
|
||||
if (empty($comment->comment_approved)) {
|
||||
$update_data = array(
|
||||
'comment_ID' => $reply['comment_id'],
|
||||
'comment_approved' => 1
|
||||
);
|
||||
wp_update_comment($update_data);
|
||||
}
|
||||
|
||||
// Build new comment parameters based on current user info and
|
||||
// the target comment for the reply.
|
||||
$data = array(
|
||||
'comment_post_ID' => $comment->comment_post_ID,
|
||||
'comment_author' => $user->display_name,
|
||||
'comment_author_email' => $user->user_email,
|
||||
'comment_author_url' => $user->user_url,
|
||||
'comment_content' => $reply['message'],
|
||||
'comment_parent' => $reply['comment_id'],
|
||||
'user_id' => $user->ID,
|
||||
'comment_date' => current_time('mysql'),
|
||||
'comment_approved' => 1
|
||||
);
|
||||
|
||||
// Create new comment based on the parameters above, and return
|
||||
// the status accordingly.
|
||||
|
||||
if (wp_insert_comment($data)) {
|
||||
$result = array('error' => false, 'message' => 'comment_replied_with_comment_author', 'values' => array($comment->comment_author));
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_reply_failed_with_error', 'values' => array($comment->comment_ID));
|
||||
}
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($reply['comment_id']));
|
||||
}
|
||||
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The edit_comment function saves new information for the
|
||||
* currently selected comment.
|
||||
*
|
||||
* @param array $params Specific params for editing a comment
|
||||
* @return array
|
||||
*/
|
||||
public function edit_comment($params) {
|
||||
|
||||
// Extract new comment info from the passed parameters
|
||||
$comment = $params['comment'];
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to moderate or edit
|
||||
// a comment then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
|
||||
$result = array('error' => true, 'message' => 'comment_edit_no_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to apply our changes.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
|
||||
// Get current comment details
|
||||
$original_comment = get_comment($comment['comment_id']);
|
||||
if ($original_comment) {
|
||||
$data = array();
|
||||
|
||||
// Replace "comment_id" with "comment_ID" since WP does not recognize
|
||||
// the small case "id".
|
||||
$comment['comment_ID'] = $original_comment->comment_ID;
|
||||
unset($comment['comment_id']);
|
||||
|
||||
// Here, we're sanitizing the input fields before we save them to the database
|
||||
// for safety and security reason. The "explode" and "implode" functions are meant
|
||||
// to maintain the line breaks associated with a textarea input/value.
|
||||
|
||||
foreach ($comment as $key => $value) {
|
||||
$data[$key] = implode("\n", array_map('sanitize_text_field', explode("\n", $value)));
|
||||
}
|
||||
|
||||
// Update existing comment based on the passed parameter fields and
|
||||
// return the status accordingly.
|
||||
|
||||
if (wp_update_comment($data)) {
|
||||
$result = array('error' => false, 'message' => 'comment_edited_with_comment_author', 'values' => array($original_comment->comment_author));
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_edit_failed_with_error', 'values' => array($original_comment->comment_ID));
|
||||
}
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($comment['comment_id']));
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The update_comment_status function is a generic handler for the following
|
||||
* comment actions:
|
||||
*
|
||||
* - approve comment
|
||||
* - unapprove comment
|
||||
* - set comment as spam
|
||||
* - move comment to trash
|
||||
* - delete comment permanently
|
||||
* - unset comment as spam
|
||||
* - restore comment
|
||||
*
|
||||
* @param array $params Specific params to update comment status
|
||||
* @return array
|
||||
*/
|
||||
public function update_comment_status($params) {
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
|
||||
|
||||
|
||||
// If user does not have sufficient privileges to moderate or edit
|
||||
// a comment then we return with error.
|
||||
|
||||
if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
|
||||
$result = array('error' => true, 'message' => 'comment_change_status_no_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to apply our changes.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
|
||||
// We make sure that we still have a valid comment from the server
|
||||
// before we apply the currently selected action.
|
||||
|
||||
$comment = get_comment($params['comment_id']);
|
||||
if ($comment) {
|
||||
$post = get_post($comment->comment_post_ID);
|
||||
|
||||
if ($post) $comment->in_response_to = $post->post_title;
|
||||
if (!empty($comment->comment_parent)) {
|
||||
$parent_comment = get_comment($comment->comment_parent);
|
||||
if ($parent_comment) $comment->in_reply_to = $parent_comment->comment_author;
|
||||
}
|
||||
|
||||
// We're formatting the comment_date to be exactly the same
|
||||
// with that of WP Comments table (e.g. 2016/12/21 at 10:30 PM)
|
||||
|
||||
$comment->comment_date = date('Y/m/d \a\t g:i a', strtotime($comment->comment_date));
|
||||
|
||||
$status = wp_get_comment_status($comment->comment_ID);
|
||||
if ($status) {
|
||||
$comment->comment_status = $status;
|
||||
}
|
||||
|
||||
$succeeded = false;
|
||||
$message = '';
|
||||
|
||||
// Here, we're using WP's wp_set_comment_status function to change the state
|
||||
// of the selected comment based on the current action, except for the "delete" action
|
||||
// where we use the wp_delete_comment to delete the comment permanently by passing
|
||||
// "true" to the second argument.
|
||||
|
||||
switch ($params['action']) {
|
||||
case 'approve':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'approve');
|
||||
$message = 'comment_approve_with_comment_author';
|
||||
break;
|
||||
case 'unapprove':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'hold');
|
||||
$message = 'comment_unapprove_with_comment_author';
|
||||
break;
|
||||
case 'spam':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'spam');
|
||||
$message = 'comment_spam_with_comment_author';
|
||||
break;
|
||||
case 'trash':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'trash');
|
||||
$message = 'comment_trash_with_comment_author';
|
||||
break;
|
||||
case 'delete':
|
||||
$succeeded = wp_delete_comment($params['comment_id'], true);
|
||||
$message = 'comment_delete_with_comment_author';
|
||||
break;
|
||||
case 'notspam':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'hold');
|
||||
$message = 'comment_not_spam_with_comment_author';
|
||||
break;
|
||||
case 'restore':
|
||||
$succeeded = wp_set_comment_status($params['comment_id'], 'hold');
|
||||
$message = 'comment_restore_with_comment_author';
|
||||
break;
|
||||
}
|
||||
|
||||
// If the current action succeeded, then we return a success message, otherwise,
|
||||
// we return an error message to the user issuing the request.
|
||||
|
||||
if ($succeeded) {
|
||||
$result = array('error' => false, 'message' => $message, 'values' => array($comment->comment_author), 'status' => $comment->comment_status, 'approved' => $comment->comment_approved);
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_change_status_failed_with_error', 'values' => array($comment->comment_ID));
|
||||
}
|
||||
} else {
|
||||
$result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($params['comment_id']));
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* - A container for RPC commands (core UpdraftCentral commands). Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
|
||||
* - Return format is array('response' => (string - a code), 'data' => (mixed));
|
||||
*
|
||||
* RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
|
||||
*/
|
||||
class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
/**
|
||||
* Retrieve site icon (favicon)
|
||||
*
|
||||
* @return array An array containing the site icon (favicon) byte string if available
|
||||
*/
|
||||
public function get_site_icon() {
|
||||
|
||||
if (!function_exists('get_site_icon_url')) {
|
||||
include_once(ABSPATH.'wp-includes/general-template.php');
|
||||
}
|
||||
|
||||
$site_icon_url = get_site_icon_url();
|
||||
|
||||
// If none is set in WordPress, let's try to search for the default favicon
|
||||
// within the site's directory
|
||||
if (empty($site_icon_url)) {
|
||||
|
||||
if (!function_exists('get_site_url')) {
|
||||
include_once(ABSPATH.'wp-includes/link-template.php');
|
||||
}
|
||||
|
||||
// Common favicon locations to check
|
||||
$potential_locations = array(
|
||||
'/favicon.ico',
|
||||
'/favicon.png',
|
||||
'/favicon.svg',
|
||||
'/assets/favicon.ico',
|
||||
'/assets/images/favicon.ico',
|
||||
'/apple-touch-icon.png',
|
||||
'/apple-touch-icon-precomposed.png',
|
||||
);
|
||||
|
||||
foreach ($potential_locations as $location) {
|
||||
$path = rtrim(ABSPATH, '/\\').$location;
|
||||
if (file_exists($path)) {
|
||||
$site_icon_url = get_site_url().$location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are returning the site icon as byte string instead of URL in order to avoid
|
||||
// any hotlink protection that might prevent us to show the icon in UpdraftCentral
|
||||
// dashboard successfully.
|
||||
$site_icon = '';
|
||||
if (!empty($site_icon_url)) {
|
||||
$content = file_get_contents($site_icon_url);
|
||||
|
||||
$mime_type = '';
|
||||
foreach ($http_response_header as $value) {
|
||||
if (false !== stripos($value, 'content-type:')) {
|
||||
list(, $mime_type) = explode(':', preg_replace('/\s+/', '', $value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($content && !empty($mime_type)) {
|
||||
$site_icon = 'data: '.$mime_type.';base64,'.base64_encode($content);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_response(array('site_icon' => $site_icon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a list of submitted commands (multiplexer)
|
||||
*
|
||||
* @param Array $query An array containing the commands to execute and a flag to indicate how to handle command execution failure.
|
||||
* @return Array An array containing the results of the process.
|
||||
*/
|
||||
public function execute_commands($query) {
|
||||
|
||||
try {
|
||||
|
||||
$commands = $query['commands'];
|
||||
$command_results = array();
|
||||
$error_count = 0;
|
||||
|
||||
/**
|
||||
* Should be one of the following options:
|
||||
* 1 = Abort on first failure
|
||||
* 2 = Abort if any command fails
|
||||
* 3 = Abort if all command fails (default)
|
||||
*/
|
||||
$error_flag = isset($query['error_flag']) ? (int) $query['error_flag'] : 3;
|
||||
|
||||
|
||||
foreach ($commands as $command => $params) {
|
||||
$command_info = apply_filters('updraftcentral_get_command_info', false, $command);
|
||||
if (!$command_info) {
|
||||
list($_prefix, $_command) = explode('.', $command);
|
||||
$command_results[$_prefix][$_command] = array('response' => 'rpcerror', 'data' => array('code' => 'unknown_rpc_command', 'data' => $command));
|
||||
|
||||
$error_count++;
|
||||
if (1 === $error_flag) break;
|
||||
} else {
|
||||
|
||||
$action = $command_info['command'];
|
||||
$command_php_class = $command_info['command_php_class'];
|
||||
|
||||
// Instantiate the command class and execute the needed action
|
||||
if (class_exists($command_php_class)) {
|
||||
$instance = new $command_php_class($this->rc);
|
||||
|
||||
if (method_exists($instance, $action)) {
|
||||
$params = empty($params) ? array() : $params;
|
||||
$call_result = call_user_func(array($instance, $action), $params);
|
||||
|
||||
$command_results[$command] = $call_result;
|
||||
if ('rpcerror' === $call_result['response'] || (isset($call_result['data']['error']) && $call_result['data']['error'])) {
|
||||
$error_count++;
|
||||
if (1 === $error_flag) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 !== $error_count) {
|
||||
// N.B. These error messages should be defined in UpdraftCentral's translation file (dashboard-translations.php)
|
||||
// before actually using this multiplexer function.
|
||||
$message = 'general_command_execution_error';
|
||||
|
||||
switch ($error_flag) {
|
||||
case 1:
|
||||
$message = 'command_execution_aborted';
|
||||
break;
|
||||
case 2:
|
||||
$message = 'failed_to_execute_some_commands';
|
||||
break;
|
||||
case 3:
|
||||
if (count($commands) === $error_count) {
|
||||
$message = 'failed_to_execute_all_commands';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$result = array('error' => true, 'message' => $message, 'values' => $command_results);
|
||||
} else {
|
||||
$result = $command_results;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the credentials entered by the user
|
||||
*
|
||||
* @param array $creds an array of filesystem credentials
|
||||
* @return array An array containing the result of the validation process.
|
||||
*/
|
||||
public function validate_credentials($creds) {
|
||||
|
||||
try {
|
||||
|
||||
$entity = $creds['entity'];
|
||||
if (isset($creds['filesystem_credentials'])) {
|
||||
parse_str($creds['filesystem_credentials'], $filesystem_credentials);
|
||||
if (is_array($filesystem_credentials)) {
|
||||
foreach ($filesystem_credentials as $key => $value) {
|
||||
// Put them into $_POST, which is where request_filesystem_credentials() checks for them.
|
||||
$_POST[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include the needed WP Core file(s)
|
||||
// template.php needed for submit_button() which is called by request_filesystem_credentials()
|
||||
$this->_admin_include('file.php', 'template.php');
|
||||
|
||||
// Directory entities that we currently need permissions
|
||||
// to update.
|
||||
$entity_directories = array(
|
||||
'plugins' => WP_PLUGIN_DIR,
|
||||
'themes' => WP_CONTENT_DIR.'/themes',
|
||||
'core' => untrailingslashit(ABSPATH)
|
||||
);
|
||||
|
||||
if ('translations' === $entity) {
|
||||
// 'en_US' don't usually have the "languages" folder, thus, we
|
||||
// check if there's a need to ask for filesystem credentials for that
|
||||
// folder if it exists, most especially for locale other than 'en_US'.
|
||||
$language_dir = WP_CONTENT_DIR.'/languages';
|
||||
if ('en_US' !== get_locale() && is_dir($language_dir)) {
|
||||
$entity_directories['translations'] = $language_dir;
|
||||
}
|
||||
}
|
||||
|
||||
$url = wp_nonce_url(site_url());
|
||||
|
||||
$passed = false;
|
||||
if (isset($entity_directories[$entity])) {
|
||||
$directory = $entity_directories[$entity];
|
||||
|
||||
// Check if credentials are valid and have sufficient
|
||||
// privileges to create and delete (e.g. write)
|
||||
ob_start();
|
||||
$credentials = request_filesystem_credentials($url, '', false, $directory);
|
||||
ob_end_clean();
|
||||
|
||||
// The "WP_Filesystem" will suffice in validating the inputted credentials
|
||||
// from UpdraftCentral, as it is already attempting to connect to the filesystem
|
||||
// using the chosen transport (e.g. ssh, ftp, etc.)
|
||||
$passed = WP_Filesystem($credentials, $directory);
|
||||
}
|
||||
|
||||
if ($passed) {
|
||||
$result = array('error' => false, 'message' => 'credentials_ok', 'values' => array());
|
||||
} else {
|
||||
// We're adding some useful error information to help troubleshooting any problems
|
||||
// that may arise in the future. If the user submitted a wrong password or username
|
||||
// it usually falls through here.
|
||||
global $wp_filesystem;
|
||||
|
||||
$errors = array();
|
||||
if (isset($wp_filesystem->errors) && is_wp_error($wp_filesystem->errors)) {
|
||||
$errors = $wp_filesystem->errors->errors;
|
||||
}
|
||||
|
||||
$result = array('error' => true, 'message' => 'failed_credentials', 'values' => array('errors' => $errors));
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => $e->getMessage(), 'values' => array());
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the FileSystem Credentials
|
||||
*
|
||||
* Extract the needed filesystem credentials (permissions) to be used
|
||||
* to update/upgrade the plugins, themes and the WP core.
|
||||
*
|
||||
* @return array $result - An array containing the creds form and some flags
|
||||
* to determine whether we need to extract the creds
|
||||
* manually from the user.
|
||||
*/
|
||||
public function get_credentials() {
|
||||
|
||||
try {
|
||||
|
||||
// Check whether user has enough permission to update entities
|
||||
if (!current_user_can('update_plugins') && !current_user_can('update_themes') && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied');
|
||||
|
||||
// Include the needed WP Core file(s)
|
||||
$this->_admin_include('file.php', 'template.php');
|
||||
|
||||
// A container that will hold the state (in this case, either true or false) of
|
||||
// each directory entities (plugins, themes, core) that will be used to determine
|
||||
// whether or not there's a need to show a form that will ask the user for their credentials
|
||||
// manually.
|
||||
$request_filesystem_credentials = array();
|
||||
|
||||
// A container for the filesystem credentials form if applicable.
|
||||
$filesystem_form = '';
|
||||
|
||||
// Directory entities that we currently need permissions
|
||||
// to update.
|
||||
$check_fs = array(
|
||||
'plugins' => WP_PLUGIN_DIR,
|
||||
'themes' => WP_CONTENT_DIR.'/themes',
|
||||
'core' => untrailingslashit(ABSPATH)
|
||||
);
|
||||
|
||||
// Here, we're looping through each entities and find output whether
|
||||
// we have sufficient permissions to update objects belonging to them.
|
||||
foreach ($check_fs as $entity => $dir) {
|
||||
|
||||
// We're determining which method to use when updating
|
||||
// the files in the filesystem.
|
||||
$filesystem_method = get_filesystem_method(array(), $dir);
|
||||
|
||||
// Buffering the output to pull the actual credentials form
|
||||
// currently being used by this WP instance if no sufficient permissions
|
||||
// is found.
|
||||
$url = wp_nonce_url(site_url());
|
||||
|
||||
ob_start();
|
||||
$filesystem_credentials_are_stored = request_filesystem_credentials($url, $filesystem_method);
|
||||
$form = strip_tags(ob_get_contents(), '<div><h2><p><input><label><fieldset><legend><span><em>');
|
||||
|
||||
if (!empty($form)) {
|
||||
$filesystem_form = $form;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
// Save the state whether or not there's a need to show the
|
||||
// credentials form to the user.
|
||||
$request_filesystem_credentials[$entity] = ('direct' !== $filesystem_method && !$filesystem_credentials_are_stored);
|
||||
}
|
||||
|
||||
// Wrapping the credentials info before passing it back
|
||||
// to the client issuing the request.
|
||||
$result = array(
|
||||
'request_filesystem_credentials' => $request_filesystem_credentials,
|
||||
'filesystem_form' => $filesystem_form
|
||||
);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$result = array('error' => true, 'message' => $e->getMessage(), 'values' => array());
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a browser-usable URL which will automatically log the user in to the site
|
||||
*
|
||||
* @param String $redirect_to - the URL to got to after logging in
|
||||
* @param Array $extra_info - valid keys are user_id, which should be a numeric user ID to log in as.
|
||||
*/
|
||||
public function get_login_url($redirect_to, $extra_info) {
|
||||
|
||||
if (is_array($extra_info) && !empty($extra_info['user_id']) && is_numeric($extra_info['user_id'])) {
|
||||
|
||||
$user_id = $extra_info['user_id'];
|
||||
|
||||
if (false == ($login_key = $this->_get_autologin_key($user_id))) return $this->_generic_error_response('user_key_failure');
|
||||
|
||||
// Default value
|
||||
$redirect_url = network_admin_url();
|
||||
if (is_array($redirect_to) && !empty($redirect_to['module'])) {
|
||||
switch ($redirect_to['module']) {
|
||||
case 'updraftplus':
|
||||
if ('initiate_restore' == $redirect_to['action'] && class_exists('UpdraftPlus_Options')) {
|
||||
$redirect_url = UpdraftPlus_Options::admin_page_url().'?page=updraftplus&udaction=initiate_restore&entities='.urlencode($redirect_to['data']['entities']).'&showdata='.urlencode($redirect_to['data']['showdata']).'&backup_timestamp='.(int) $redirect_to['data']['backup_timestamp'];
|
||||
|
||||
} elseif ('download_file' == $redirect_to['action']) {
|
||||
$findex = empty($redirect_to['data']['findex']) ? 0 : (int) $redirect_to['data']['findex'];
|
||||
// e.g. ?udcentral_action=dl&action=updraftplus_spool_file&backup_timestamp=1455101696&findex=0&what=plugins
|
||||
$redirect_url = site_url().'?udcentral_action=spool_file&action=updraftplus_spool_file&findex='.$findex.'&what='.urlencode($redirect_to['data']['what']).'&backup_timestamp='.(int) $redirect_to['data']['backup_timestamp'];
|
||||
}
|
||||
break;
|
||||
case 'direct_url':
|
||||
$redirect_url = $redirect_to['url'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$login_key = apply_filters('updraftplus_remotecontrol_login_key', array(
|
||||
'key' => $login_key,
|
||||
'created' => time(),
|
||||
'redirect_url' => $redirect_url
|
||||
), $redirect_to, $extra_info);
|
||||
|
||||
// Over-write any previous value - only one can be valid at a time)
|
||||
update_user_meta($user_id, 'updraftcentral_login_key', $login_key);
|
||||
|
||||
return $this->_response(array(
|
||||
'login_url' => network_site_url('?udcentral_action=login&login_id='.$user_id.'&login_key='.$login_key['key'])
|
||||
));
|
||||
|
||||
} else {
|
||||
return $this->_generic_error_response('user_unknown');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information derived from phpinfo()
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function phpinfo() {
|
||||
$phpinfo = $this->_get_phpinfo_array();
|
||||
|
||||
if (!empty($phpinfo)) {
|
||||
return $this->_response($phpinfo);
|
||||
}
|
||||
|
||||
return $this->_generic_error_response('phpinfo_fail');
|
||||
}
|
||||
|
||||
/**
|
||||
* The key obtained is only intended to be short-lived. Hence, there's no intention other than that it is random and only used once - only the most recent one is valid.
|
||||
*
|
||||
* @param Integer $user_id Specific user ID to get the autologin key
|
||||
* @return Array
|
||||
*/
|
||||
public function _get_autologin_key($user_id) {
|
||||
$secure_auth_key = defined('SECURE_AUTH_KEY') ? SECURE_AUTH_KEY : hash('sha256', DB_PASSWORD).'_'.rand(0, 999999999);
|
||||
if (!defined('SECURE_AUTH_KEY')) return false;
|
||||
$hash_it = $user_id.'_'.microtime(true).'_'.rand(0, 999999999).'_'.$secure_auth_key;
|
||||
$hash = hash('sha256', $hash_it);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
public function site_info() {
|
||||
global $wpdb;
|
||||
|
||||
// THis is included so we can get $wp_version
|
||||
@include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function.
|
||||
|
||||
$ud_version = is_a($this->ud, 'UpdraftPlus') ? $this->ud->version : 'none';
|
||||
|
||||
return $this->_response(array(
|
||||
'versions' => array(
|
||||
'ud' => $ud_version,
|
||||
'php' => PHP_VERSION,
|
||||
'wp' => $wp_version,// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
|
||||
'mysql' => $wpdb->db_version(),
|
||||
'udrpc_php' => $this->rc->udrpc_version,
|
||||
),
|
||||
'bloginfo' => array(
|
||||
'url' => network_site_url(),
|
||||
'name' => get_bloginfo('name'),
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* This calls the WP_Action within WP
|
||||
*
|
||||
* @param array $data Array of Data to be used within call_wp_action
|
||||
* @return array
|
||||
*/
|
||||
public function call_wordpress_action($data) {
|
||||
if (false === ($updraftplus_admin = $this->_load_ud_admin())) return $this->_generic_error_response('no_updraftplus');
|
||||
$response = $updraftplus_admin->call_wp_action($data);
|
||||
|
||||
if (empty($data["wpaction"])) {
|
||||
return $this->_generic_error_response("error", "no command sent");
|
||||
}
|
||||
|
||||
return $this->_response(array(
|
||||
"response" => $response['response'],
|
||||
"status" => $response['status'],
|
||||
"log" => $response['log']
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disk space used
|
||||
*
|
||||
* @uses UpdraftPlus_Filesystem_Functions::get_disk_space_used()
|
||||
*
|
||||
* @param String $entity - the entity to count (e.g. 'plugins', 'themes')
|
||||
*
|
||||
* @return Array - response
|
||||
*/
|
||||
public function count($entity) {
|
||||
if (!class_exists('UpdraftPlus_Filesystem_Functions')) return $this->_generic_error_response('no_updraftplus');
|
||||
$response = UpdraftPlus_Filesystem_Functions::get_disk_space_used($entity);
|
||||
|
||||
return $this->_response($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* https://secure.php.net/phpinfo
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
private function _get_phpinfo_array() {
|
||||
if (!function_exists('phpinfo')) return null;
|
||||
ob_start();
|
||||
phpinfo(INFO_GENERAL|INFO_CREDITS|INFO_MODULES);
|
||||
$phpinfo = array('phpinfo' => array());
|
||||
|
||||
if (preg_match_all('#(?:<h2>(?:<a name=".*?">)?(.*?)(?:</a>)?</h2>)|(?:<tr(?: class=".*?")?><t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>)?)?</tr>)#s', ob_get_clean(), $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $match) {
|
||||
if (strlen($match[1])) {
|
||||
$phpinfo[$match[1]] = array();
|
||||
} elseif (isset($match[3])) {
|
||||
$keys1 = array_keys($phpinfo);
|
||||
$phpinfo[end($keys1)][$match[2]] = isset($match[4]) ? array($match[3], $match[4]) : $match[3];
|
||||
} else {
|
||||
$keys1 = array_keys($phpinfo);
|
||||
$phpinfo[end($keys1)][] = $match[2];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return $phpinfo;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an UpdraftPlus_Admin object
|
||||
*
|
||||
* @return UpdraftPlus_Admin|Boolean - false in case of failure
|
||||
*/
|
||||
private function _load_ud_admin() {
|
||||
if (!defined('UPDRAFTPLUS_DIR') || !is_file(UPDRAFTPLUS_DIR.'/admin.php')) return false;
|
||||
updraft_try_include_file('admin.php', 'include_once');
|
||||
global $updraftplus_admin;
|
||||
return $updraftplus_admin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,601 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles Media Commands
|
||||
*/
|
||||
class UpdraftCentral_Media_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
private $switched = false;
|
||||
|
||||
/**
|
||||
* Function that gets called before every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _pre_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- This function is called from listener.php and $extra_info is being sent.
|
||||
// Here we assign the current blog_id to a variable $blog_id
|
||||
$blog_id = get_current_blog_id();
|
||||
if (!empty($data['site_id'])) $blog_id = $data['site_id'];
|
||||
|
||||
if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
|
||||
$this->switched = switch_to_blog($blog_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that gets called after every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _post_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Unused parameter is present because the caller from UpdraftCentral_Listener class uses 3 arguments.
|
||||
// Here, we're restoring to the current (default) blog before we switched
|
||||
if ($this->switched) restore_current_blog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and retrieves posts based from the submitted parameters
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function get_media_items($params) {
|
||||
$error = $this->_validate_capabilities(array('upload_files', 'edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
// check paged parameter; if empty set to defaults
|
||||
$paged = !empty($params['paged']) ? (int) $params['paged'] : 1;
|
||||
$numberposts = !empty($params['numberposts']) ? (int) $params['numberposts'] : 10;
|
||||
$offset = ($paged - 1) * $numberposts;
|
||||
|
||||
$args = array(
|
||||
'posts_per_page' => $numberposts,
|
||||
'paged' => $paged,
|
||||
'offset' => $offset,
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
);
|
||||
|
||||
if (!empty($params['keyword'])) {
|
||||
$args['s'] = $params['keyword'];
|
||||
}
|
||||
|
||||
if (!empty($params['category'])) {
|
||||
if (in_array($params['category'], array('detached', 'unattached'))) {
|
||||
$attachment_ids = $this->get_unattached_ids();
|
||||
} else {
|
||||
$attachment_ids = $this->get_type_ids($params['category']);
|
||||
}
|
||||
|
||||
$args['post__in'] = $attachment_ids;
|
||||
}
|
||||
|
||||
if (!empty($params['date'])) {
|
||||
list($monthnum, $year) = explode(':', $params['date']);
|
||||
|
||||
$args['monthnum'] = $monthnum;
|
||||
$args['year'] = $year;
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
$result = $query->posts;
|
||||
|
||||
$count_posts = (int) $query->found_posts;
|
||||
$page_count = 0;
|
||||
|
||||
if ($count_posts > 0) {
|
||||
$page_count = absint($count_posts / $numberposts);
|
||||
$remainder = absint($count_posts % $numberposts);
|
||||
$page_count = ($remainder > 0) ? ++$page_count : $page_count;
|
||||
}
|
||||
|
||||
$info = array(
|
||||
'page' => $paged,
|
||||
'pages' => $page_count,
|
||||
'results' => $count_posts,
|
||||
'items_from' => (($paged * $numberposts) - $numberposts) + 1,
|
||||
'items_to' => ($paged == $page_count) ? $count_posts : $paged * $numberposts,
|
||||
);
|
||||
|
||||
$media_items = array();
|
||||
if (!empty($result)) {
|
||||
foreach ($result as $item) {
|
||||
$media = $this->get_media_item($item, null, true);
|
||||
if (!empty($media)) {
|
||||
array_push($media_items, $media);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'items' => $media_items,
|
||||
'info' => $info,
|
||||
'options' => array(
|
||||
'date' => $this->get_date_options(),
|
||||
'type' => $this->get_type_options()
|
||||
)
|
||||
);
|
||||
|
||||
return $this->_response($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we have an image editor (e.g. GD, Imagick, etc.) set in place to handle the basic editing
|
||||
* functions such as rotate, crop, etc. If not, then we hide that feature in UpdraftCentral
|
||||
*
|
||||
* @param object $media The media item/object to check
|
||||
* @return boolean
|
||||
*/
|
||||
private function has_image_editor($media) {
|
||||
// Most of the time image library are enabled by default in the php.ini but there's a possbility that users don't
|
||||
// enable them as they have no need for them at the moment or for some other reasons. Thus, we need to confirm
|
||||
// that here through the wp_get_image_editor method.
|
||||
$has_image_editor = true;
|
||||
if (!empty($media)) {
|
||||
if (!function_exists('wp_get_image_editor')) {
|
||||
require_once(ABSPATH.'wp-includes/media.php');
|
||||
}
|
||||
|
||||
if (!function_exists('_load_image_to_edit_path')) {
|
||||
require_once(ABSPATH.'wp-admin/includes/image.php');
|
||||
}
|
||||
|
||||
$image_editor = wp_get_image_editor(_load_image_to_edit_path($media->ID));
|
||||
if (is_wp_error($image_editor)) {
|
||||
$has_image_editor = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $has_image_editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single media item information
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @param array|null $extra_info Additional information from the current request
|
||||
* @param boolean $raw If set, returns the result of the fetch process unwrapped by the response array
|
||||
* @return array
|
||||
*/
|
||||
public function get_media_item($params, $extra_info = null, $raw = false) {
|
||||
$error = $this->_validate_capabilities(array('upload_files', 'edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
// Raw means that we need to return the result without wrapping it
|
||||
// with the "$this->_response" function which indicates that the call
|
||||
// was done locally (within the class) and not directly from UpdraftCentral.
|
||||
if ($raw && is_object($params) && isset($params->ID)) {
|
||||
$media = $params;
|
||||
} elseif (is_array($params) && !empty($params['id'])) {
|
||||
$media = get_post($params['id']);
|
||||
}
|
||||
|
||||
if (!function_exists('get_post_mime_types')) {
|
||||
global $updraftcentral_main;
|
||||
|
||||
// For a much later version of WP the "get_post_mime_types" is located
|
||||
// in a different folder. So, we make sure that we have it loaded before
|
||||
// actually using it.
|
||||
if (version_compare($updraftcentral_main->get_wordpress_version(), '3.5', '>=')) {
|
||||
require_once(ABSPATH.WPINC.'/post.php');
|
||||
} else {
|
||||
// For WP 3.4, the "get_post_mime_types" is located in the location provided below.
|
||||
require_once(ABSPATH.'wp-admin/includes/post.php');
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('wp_image_editor')) {
|
||||
require_once(ABSPATH.'wp-admin/includes/image-edit.php');
|
||||
}
|
||||
|
||||
if (!function_exists('get_media_item')) {
|
||||
require_once(ABSPATH.'wp-admin/includes/template.php');
|
||||
require_once(ABSPATH.'wp-admin/includes/media.php');
|
||||
}
|
||||
|
||||
|
||||
if ($media) {
|
||||
$thumb = wp_get_attachment_image_src($media->ID, 'thumbnail', true);
|
||||
if (!empty($thumb)) $media->thumb_url = $thumb[0];
|
||||
|
||||
$media->url = wp_get_attachment_url($media->ID);
|
||||
$media->parent_post_title = get_the_title($media->post_parent);
|
||||
$media->author = get_the_author_meta('display_name', $media->post_author);
|
||||
$media->filename = basename($media->url);
|
||||
$media->date = date('Y/m/d', strtotime($media->post_date));
|
||||
$media->upload_date = mysql2date(get_option('date_format'), $media->post_date);
|
||||
|
||||
$media->filesize = 0;
|
||||
$file = get_attached_file($media->ID);
|
||||
if (!empty($file) && file_exists($file)) {
|
||||
$media->filesize = size_format(filesize($file));
|
||||
}
|
||||
|
||||
$media->nonce = wp_create_nonce('image_editor-'.$media->ID);
|
||||
if (false !== strpos($media->post_mime_type, 'image/')) {
|
||||
$meta = wp_get_attachment_metadata($media->ID);
|
||||
|
||||
$thumb = image_get_intermediate_size($media->ID, 'thumbnail');
|
||||
$sub_sizes = isset($meta['sizes']) && is_array($meta['sizes']);
|
||||
|
||||
// Pulling details
|
||||
$sizer = 1;
|
||||
if (isset($meta['width'], $meta['height'])) {
|
||||
$big = max($meta['width'], $meta['height']);
|
||||
$sizer = $big > 400 ? 400 / $big : 1;
|
||||
}
|
||||
|
||||
$constrained_dims = array();
|
||||
if ($thumb && $sub_sizes) {
|
||||
$constrained_dims = wp_constrain_dimensions($thumb['width'], $thumb['height'], 160, 120);
|
||||
}
|
||||
|
||||
$rotate_supported = false;
|
||||
if (function_exists('imagerotate') || wp_image_editor_supports(array('mime_type' => get_post_mime_type($media->ID), 'methods' => array('rotate')))) {
|
||||
$rotate_supported = true;
|
||||
}
|
||||
|
||||
// Check for alternative text if present
|
||||
$alt = get_post_meta($media->ID, '_wp_attachment_image_alt', true);
|
||||
$media->alt = !empty($alt) ? $alt : '';
|
||||
|
||||
// Check whether edited images are restorable
|
||||
$backup_sizes = get_post_meta($media->ID, '_wp_attachment_backup_sizes', true);
|
||||
$can_restore = !empty($backup_sizes) && isset($backup_sizes['full-orig']) && basename($meta['file']) != $backup_sizes['full-orig']['file'];
|
||||
|
||||
$image_edit_overwrite = (!defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE) ? 0 : 1;
|
||||
$media->misc = array(
|
||||
'sizer' => $sizer,
|
||||
'rand' => rand(1, 99999),
|
||||
'constrained_dims' => $constrained_dims,
|
||||
'rotate_supported' => (int) $rotate_supported,
|
||||
'thumb' => $thumb,
|
||||
'meta' => $meta,
|
||||
'alt_text' => $alt,
|
||||
'can_restore' => $can_restore,
|
||||
'image_edit_overwrite' => $image_edit_overwrite
|
||||
);
|
||||
|
||||
$media->has_image_editor = $this->has_image_editor($media);
|
||||
}
|
||||
}
|
||||
|
||||
return $raw ? $media : $this->_response(array('item' => $media));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and retrieves posts based from the submitted parameters
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function get_posts($params) {
|
||||
$error = $this->_validate_capabilities(array('edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
// check paged parameter; if empty set to defaults
|
||||
$paged = !empty($params['paged']) ? (int) $params['paged'] : 1;
|
||||
$numberposts = !empty($params['numberposts']) ? (int) $params['numberposts'] : 10;
|
||||
$offset = ($paged - 1) * $numberposts;
|
||||
|
||||
$args = array(
|
||||
'posts_per_page' => $numberposts,
|
||||
'paged' => $paged,
|
||||
'offset' => $offset,
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish,private,draft,pending,future',
|
||||
);
|
||||
|
||||
if (!empty($params['keyword'])) {
|
||||
$args['s'] = $params['keyword'];
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
$result = $query->posts;
|
||||
|
||||
$count_posts = (int) $query->found_posts;
|
||||
$page_count = 0;
|
||||
|
||||
if ($count_posts > 0) {
|
||||
$page_count = absint($count_posts / $numberposts);
|
||||
$remainder = absint($count_posts % $numberposts);
|
||||
$page_count = ($remainder > 0) ? ++$page_count : $page_count;
|
||||
}
|
||||
|
||||
$info = array(
|
||||
'page' => $paged,
|
||||
'pages' => $page_count,
|
||||
'results' => $count_posts,
|
||||
'items_from' => (($paged * $numberposts) - $numberposts) + 1,
|
||||
'items_to' => ($paged == $page_count) ? $count_posts : $paged * $numberposts,
|
||||
);
|
||||
|
||||
$posts = array();
|
||||
if (!empty($result)) {
|
||||
foreach ($result as $post) {
|
||||
array_push($posts, array('ID' => $post->ID, 'title' => $post->post_title));
|
||||
}
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'posts' => $posts,
|
||||
'info' => $info
|
||||
);
|
||||
return $this->_response($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves media changes from UpdraftCentral
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function save_media_item($params) {
|
||||
$error = $this->_validate_capabilities(array('upload_files', 'edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
$args = array(
|
||||
'post_title' => $params['image_title'],
|
||||
'post_excerpt' => $params['image_caption'],
|
||||
'post_content' => $params['image_description']
|
||||
);
|
||||
|
||||
if (!empty($params['new'])) {
|
||||
$args['post_type'] = 'attachment';
|
||||
$media_id = wp_insert_post($args, true);
|
||||
} else {
|
||||
$args['ID'] = $params['id'];
|
||||
$args['post_modified'] = date('Y-m-d H:i:s');
|
||||
$args['post_modified_gmt'] = gmdate('Y-m-d H:i:s');
|
||||
|
||||
$media_id = wp_update_post($args, true);
|
||||
}
|
||||
|
||||
if (!empty($media_id)) {
|
||||
// Update alternative text if not empty
|
||||
if (!empty($params['image_alternative_text'])) {
|
||||
update_post_meta($media_id, '_wp_attachment_image_alt', $params['image_alternative_text']);
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'status' => 'success',
|
||||
'item' => $this->get_media_item(array('id' => $media_id), null, true)
|
||||
);
|
||||
} else {
|
||||
$result = array('status' => 'failed');
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes media action (e.g. attach, detach and delete)
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function execute_media_action($params) {
|
||||
global $updraftcentral_host_plugin;
|
||||
|
||||
$error = $this->_validate_capabilities(array('upload_files', 'edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
$result = array();
|
||||
switch ($params['do']) {
|
||||
case 'attach':
|
||||
global $wpdb;
|
||||
$query_result = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET `post_parent` = %d WHERE `post_type` = 'attachment' AND ID = %d", $params['parent_id'], $params['id']));
|
||||
|
||||
if (false === $query_result) {
|
||||
$result['error'] = $updraftcentral_host_plugin->retrieve_show_message('failed_to_attach_media');
|
||||
} else {
|
||||
$result['msg'] = $updraftcentral_host_plugin->retrieve_show_message('media_attached');
|
||||
}
|
||||
break;
|
||||
case 'detach':
|
||||
global $wpdb;
|
||||
$query_result = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET `post_parent` = 0 WHERE `post_type` = 'attachment' AND ID = %d", $params['id']));
|
||||
|
||||
if (false === $query_result) {
|
||||
$result['error'] = $updraftcentral_host_plugin->retrieve_show_message('failed_to_detach_media');
|
||||
} else {
|
||||
$result['msg'] = $updraftcentral_host_plugin->retrieve_show_message('media_detached');
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
$failed_items = array();
|
||||
foreach ($params['ids'] as $id) {
|
||||
// Delete permanently
|
||||
if (false === wp_delete_attachment($id, true)) {
|
||||
$failed_items[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($failed_items)) {
|
||||
$result['error'] = $updraftcentral_host_plugin->retrieve_show_message('failed_to_delete_media');
|
||||
$result['items'] = $failed_items;
|
||||
} else {
|
||||
$result['msg'] = $updraftcentral_host_plugin->retrieve_show_message('selected_media_deleted');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a collection of formatted dates found for the given post statuses.
|
||||
* It will be used as options for the date filter when managing the media items in UpdraftCentral.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_date_options() {
|
||||
global $wpdb;
|
||||
$options = array();
|
||||
|
||||
$date_options = $wpdb->get_col("SELECT DATE_FORMAT(`post_date`, '%M %Y') as `formatted_post_date` FROM {$wpdb->posts} WHERE `post_type` = 'attachment' AND `post_status` = 'inherit' GROUP BY `formatted_post_date` ORDER BY `post_date` DESC");
|
||||
|
||||
if (!empty($date_options)) {
|
||||
foreach ($date_options as $monthyear) {
|
||||
$timestr = strtotime($monthyear);
|
||||
$options[] = array('label' => date('F Y', $timestr), 'value' => date('n:Y', $timestr));
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves mime types that will be use as filter option in UpdraftCentral
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_type_options() {
|
||||
global $wpdb, $updraftcentral_host_plugin, $updraftcentral_main;
|
||||
|
||||
$options = array();
|
||||
if (!function_exists('get_post_mime_types')) {
|
||||
// For a much later version of WP the "get_post_mime_types" is located
|
||||
// in a different folder. So, we make sure that we have it loaded before
|
||||
// actually using it.
|
||||
if (version_compare($updraftcentral_main->get_wordpress_version(), '3.5', '>=')) {
|
||||
require_once(ABSPATH.WPINC.'/post.php');
|
||||
} else {
|
||||
// For WP 3.4, the "get_post_mime_types" is located in the location provided below.
|
||||
require_once(ABSPATH.'wp-admin/includes/post.php');
|
||||
}
|
||||
}
|
||||
|
||||
$post_mime_types = get_post_mime_types();
|
||||
$type_options = $wpdb->get_col("SELECT `post_mime_type` FROM {$wpdb->posts} WHERE `post_type` = 'attachment' AND `post_status` = 'inherit' GROUP BY `post_mime_type` ORDER BY `post_mime_type` DESC");
|
||||
|
||||
foreach ($post_mime_types as $mime_type => $label) {
|
||||
if (!wp_match_mime_types($mime_type, $type_options)) continue;
|
||||
$options[] = array('label' => $label[0], 'value' => esc_attr($mime_type));
|
||||
}
|
||||
|
||||
$options[] = array('label' => $updraftcentral_host_plugin->retrieve_show_message('unattached'), 'value' => 'detached');
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves media items that haven't been attached to any posts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_unattached_ids() {
|
||||
global $wpdb;
|
||||
return $wpdb->get_col("SELECT `ID` FROM {$wpdb->posts} WHERE `post_type` = 'attachment' AND `post_status` = 'inherit' AND `post_parent` = '0'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves IDs of media items that has the given mime type
|
||||
*
|
||||
* @param string $type The mime type to search for
|
||||
* @return array
|
||||
*/
|
||||
private function get_type_ids($type) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_col($wpdb->prepare("SELECT `ID` FROM {$wpdb->posts} WHERE `post_type` = 'attachment' AND `post_status` = 'inherit' AND `post_mime_type` LIKE %s", $type.'/%'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we have the required fields submitted and the user has
|
||||
* the capabilities to execute the requested action
|
||||
*
|
||||
* @param array $capabilities The capabilities to check and validate
|
||||
*
|
||||
* @return array|void
|
||||
*/
|
||||
private function _validate_capabilities($capabilities) {
|
||||
foreach ($capabilities as $capability) {
|
||||
if (!current_user_can($capability)) {
|
||||
return $this->_generic_error_response('insufficient_permission');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the $_REQUEST global variable with the submitted data
|
||||
*
|
||||
* @param array $params Submitted data received from UpdraftCentral
|
||||
* @return array
|
||||
*/
|
||||
private function populate_request($params) {
|
||||
if (!empty($params)) {
|
||||
foreach ($params as $key => $value) {
|
||||
$_REQUEST[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles image editing requests coming from UpdraftCentral
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function image_editor($params) {
|
||||
$error = $this->_validate_capabilities(array('edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
$attachment_id = (int) $params['postid'];
|
||||
$this->populate_request($params);
|
||||
|
||||
if (!function_exists('load_image_to_edit')) {
|
||||
require_once(ABSPATH.'wp-admin/includes/image.php');
|
||||
}
|
||||
|
||||
include_once(ABSPATH.'wp-admin/includes/image-edit.php');
|
||||
$msg = false;
|
||||
switch ($params['do']) {
|
||||
case 'save':
|
||||
case 'scale':
|
||||
$msg = wp_save_image($attachment_id);
|
||||
break;
|
||||
case 'restore':
|
||||
$msg = wp_restore_image($attachment_id);
|
||||
break;
|
||||
}
|
||||
|
||||
$msg = (false !== $msg) ? json_encode($msg) : $msg;
|
||||
return $this->_response(array('content' => $msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles image preview requests coming from UpdraftCentral
|
||||
*
|
||||
* @param array $params Containing all the needed information to filter the results of the current request
|
||||
* @return array
|
||||
*/
|
||||
public function image_preview($params) {
|
||||
$error = $this->_validate_capabilities(array('edit_posts'));
|
||||
if (!empty($error)) return $error;
|
||||
|
||||
if (!function_exists('load_image_to_edit')) {
|
||||
require_once(ABSPATH.'wp-admin/includes/image.php');
|
||||
}
|
||||
|
||||
include_once(ABSPATH.'wp-admin/includes/image-edit.php');
|
||||
$this->populate_request($params);
|
||||
$post_id = (int) $params['postid'];
|
||||
|
||||
ob_start();
|
||||
stream_preview_image($post_id);
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $this->_response(array('content' => base64_encode($content)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
// Load the posts command class since we're going to be extending it for our page module service/command
|
||||
// class in order to minimize redundant shareable methods.
|
||||
if (!class_exists('UpdraftCentral_Posts_Commands')) require_once('posts.php');
|
||||
|
||||
/**
|
||||
* Handles Pages Commands
|
||||
*/
|
||||
class UpdraftCentral_Pages_Commands extends UpdraftCentral_Posts_Commands {
|
||||
|
||||
protected $post_type = 'page';
|
||||
}
|
||||
@@ -0,0 +1,700 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles UpdraftCentral Plugin Commands which basically handles
|
||||
* the installation and activation of a plugin
|
||||
*/
|
||||
class UpdraftCentral_Plugin_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
private $switched = false;
|
||||
|
||||
/**
|
||||
* Function that gets called before every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _pre_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- This function is called from listener.php and $extra_info is being sent.
|
||||
// Here we assign the current blog_id to a variable $blog_id
|
||||
$blog_id = get_current_blog_id();
|
||||
if (!empty($data['site_id'])) $blog_id = $data['site_id'];
|
||||
|
||||
if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
|
||||
$this->switched = switch_to_blog($blog_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that gets called after every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _post_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Unused parameter is present because the caller from UpdraftCentral_Listener class uses 3 arguments.
|
||||
// Here, we're restoring to the current (default) blog before we switched
|
||||
if ($this->switched) restore_current_blog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_admin_include('plugin.php', 'file.php', 'template.php', 'class-wp-upgrader.php', 'plugin-install.php', 'update.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs and activates a plugin through upload
|
||||
*
|
||||
* @param array $params Parameter array containing information pertaining the currently uploaded plugin
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function upload_plugin($params) {
|
||||
return $this->process_chunk_upload($params, 'plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the plugin is currently installed and activated.
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the plugin to check
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function is_plugin_installed($query) {
|
||||
|
||||
if (!isset($query['plugin']))
|
||||
return $this->_generic_error_response('plugin_name_required');
|
||||
|
||||
|
||||
$result = $this->_get_plugin_info($query);
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies currently requested action for plugin processing
|
||||
*
|
||||
* @param string $action The action to apply (e.g. activate or install)
|
||||
* @param array $query Parameter array containing information for the currently requested action
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _apply_plugin_action($action, $query) {
|
||||
|
||||
$result = array();
|
||||
switch ($action) {
|
||||
case 'activate':
|
||||
case 'network_activate':
|
||||
$info = $this->_get_plugin_info($query);
|
||||
if ($info['installed']) {
|
||||
$activate = activate_plugin($info['plugin_path']);
|
||||
if (is_wp_error($activate)) {
|
||||
$result = $this->_generic_error_response('generic_response_error', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'generic_response_error',
|
||||
'error_message' => $activate->get_error_message(),
|
||||
'info' => $this->_get_plugin_info($query)
|
||||
));
|
||||
} else {
|
||||
$result = array('activated' => true, 'info' => $this->_get_plugin_info($query), 'last_state' => $info);
|
||||
}
|
||||
} else {
|
||||
$result = $this->_generic_error_response('plugin_not_installed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'plugin_not_installed',
|
||||
'error_message' => __('The plugin you wish to activate is either not installed or has been removed recently.', 'updraftplus'),
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 'deactivate':
|
||||
case 'network_deactivate':
|
||||
$info = $this->_get_plugin_info($query);
|
||||
if ($info['active']) {
|
||||
deactivate_plugins($info['plugin_path']);
|
||||
if (!is_plugin_active($info['plugin_path'])) {
|
||||
$result = array('deactivated' => true, 'info' => $this->_get_plugin_info($query), 'last_state' => $info);
|
||||
} else {
|
||||
$result = $this->_generic_error_response('deactivate_plugin_failed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'deactivate_plugin_failed',
|
||||
'error_message' => __('There appears to be a problem deactivating the intended plugin.', 'updraftplus').' '.__('Please check your permissions and try again.', 'updraftplus'),
|
||||
'info' => $this->_get_plugin_info($query)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$result = $this->_generic_error_response('not_active', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'not_active',
|
||||
'error_message' => __('The plugin you wish to deactivate is currently not active or is already deactivated.', 'updraftplus'),
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 'install':
|
||||
$api = plugins_api('plugin_information', array(
|
||||
'slug' => $query['slug'],
|
||||
'fields' => array(
|
||||
'short_description' => false,
|
||||
'sections' => false,
|
||||
'requires' => false,
|
||||
'rating' => false,
|
||||
'ratings' => false,
|
||||
'downloaded' => false,
|
||||
'last_updated' => false,
|
||||
'added' => false,
|
||||
'tags' => false,
|
||||
'compatibility' => false,
|
||||
'homepage' => false,
|
||||
'donate_link' => false,
|
||||
)
|
||||
));
|
||||
|
||||
$info = $this->_get_plugin_info($query);
|
||||
if (is_wp_error($api)) {
|
||||
$result = $this->_generic_error_response('generic_response_error', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'generic_response_error',
|
||||
'error_message' => $api->get_error_message(),
|
||||
'info' => $info
|
||||
));
|
||||
} else {
|
||||
$installed = $info['installed'];
|
||||
|
||||
$error_code = $error_message = '';
|
||||
if (!$installed) {
|
||||
// WP < 3.7
|
||||
if (!class_exists('Automatic_Upgrader_Skin')) include_once(dirname(dirname(__FILE__)).'/classes/class-automatic-upgrader-skin.php');
|
||||
|
||||
$skin = new Automatic_Upgrader_Skin();
|
||||
$upgrader = new Plugin_Upgrader($skin);
|
||||
|
||||
$download_link = $api->download_link;
|
||||
$installed = $upgrader->install($download_link);
|
||||
|
||||
if (is_wp_error($installed)) {
|
||||
$error_code = $installed->get_error_code();
|
||||
$error_message = $installed->get_error_message();
|
||||
} elseif (is_wp_error($skin->result)) {
|
||||
$error_code = $skin->result->get_error_code();
|
||||
$error_message = $skin->result->get_error_message();
|
||||
|
||||
$error_data = $skin->result->get_error_data($error_code);
|
||||
if (!empty($error_data)) {
|
||||
if (is_array($error_data)) $error_data = json_encode($error_data);
|
||||
$error_message .= ' '.$error_data;
|
||||
}
|
||||
} elseif (is_null($installed) || !$installed) {
|
||||
global $wp_filesystem;
|
||||
$upgrade_messages = $skin->get_upgrade_messages();
|
||||
|
||||
if (!class_exists('WP_Filesystem_Base')) include_once(ABSPATH.'/wp-admin/includes/class-wp-filesystem-base.php');
|
||||
|
||||
// Pass through the error from WP_Filesystem if one was raised.
|
||||
if ($wp_filesystem instanceof WP_Filesystem_Base && is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
|
||||
$error_code = $wp_filesystem->errors->get_error_code();
|
||||
$error_message = $wp_filesystem->errors->get_error_message();
|
||||
} elseif (!empty($upgrade_messages)) {
|
||||
// We're only after for the last feedback that we received from the install process. Mostly,
|
||||
// that is where the last error has been inserted.
|
||||
$messages = $skin->get_upgrade_messages();
|
||||
$error_code = 'install_failed';
|
||||
$error_message = end($messages);
|
||||
} else {
|
||||
$error_code = 'unable_to_connect_to_filesystem';
|
||||
$error_message = __('Unable to connect to the filesystem.', 'updraftplus').' '.__('Please confirm your credentials.', 'updraftplus');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$installed || is_wp_error($installed)) {
|
||||
$result = $this->_generic_error_response('plugin_install_failed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => $error_code,
|
||||
'error_message' => $error_message,
|
||||
'info' => $this->_get_plugin_info($query)
|
||||
));
|
||||
} else {
|
||||
$result = array('installed' => true, 'info' => $this->_get_plugin_info($query), 'last_state' => $info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the submitted credentials to the global $_POST variable
|
||||
*
|
||||
* @param array $query Parameter array containing information for the currently requested action
|
||||
*/
|
||||
private function _preload_credentials($query) {
|
||||
if (!empty($query) && isset($query['filesystem_credentials'])) {
|
||||
parse_str($query['filesystem_credentials'], $filesystem_credentials);
|
||||
if (is_array($filesystem_credentials)) {
|
||||
foreach ($filesystem_credentials as $key => $value) {
|
||||
// Put them into $_POST, which is where request_filesystem_credentials() checks for them.
|
||||
$_POST[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we have the required fields submitted and the user has
|
||||
* the capabilities to execute the requested action
|
||||
*
|
||||
* @param array $query The submitted information
|
||||
* @param array $fields The required fields to check
|
||||
* @param array $capabilities The capabilities to check and validate
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function _validate_fields_and_capabilities($query, $fields, $capabilities) {
|
||||
|
||||
$error = '';
|
||||
if (!empty($fields)) {
|
||||
for ($i=0; $i<count($fields); $i++) {
|
||||
$field = $fields[$i];
|
||||
|
||||
if (!isset($query[$field])) {
|
||||
if ('keyword' === $field) {
|
||||
$error = $this->_generic_error_response('keyword_required');
|
||||
} else {
|
||||
$error = $this->_generic_error_response('plugin_'.$query[$field].'_required');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($error) && !empty($capabilities)) {
|
||||
for ($i=0; $i<count($capabilities); $i++) {
|
||||
if (!current_user_can($capabilities[$i])) {
|
||||
$error = $this->_generic_error_response('plugin_insufficient_permission');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing an action for multiple items
|
||||
*
|
||||
* @param array $query Parameter array containing a list of plugins to process
|
||||
* @return array Contains the results of the bulk process
|
||||
*/
|
||||
public function process_action_in_bulk($query) {
|
||||
$action = isset($query['action']) ? $query['action'] : '';
|
||||
$items = isset($query['args']) ? $query['args']['items'] : array();
|
||||
|
||||
$results = array();
|
||||
if (!empty($action) && !empty($items) && is_array($items)) {
|
||||
foreach ($items as $value) {
|
||||
if (method_exists($this, $action)) {
|
||||
$results[] = $this->$action($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_response($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the plugin to activate
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function activate_plugin($query) {
|
||||
|
||||
$fields = array('plugin');
|
||||
$permissions = array('activate_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_plugin_action((!empty($query['multisite']) && (bool) $query['multisite']) ? 'network_activate' : 'activate', $query);
|
||||
if (empty($result['activated'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the plugin to deactivate
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function deactivate_plugin($query) {
|
||||
|
||||
$fields = array('plugin');
|
||||
$permissions = array('activate_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_plugin_action((!empty($query['multisite']) && (bool) $query['multisite']) ? 'network_deactivate' : 'deactivate', $query);
|
||||
if (empty($result['deactivated'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download, install and activates the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the plugin name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function install_activate_plugin($query) {
|
||||
|
||||
$fields = array('plugin', 'slug');
|
||||
$permissions = array('install_plugins', 'activate_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_plugin_action('install', $query);
|
||||
if (!empty($result['installed']) && $result['installed']) {
|
||||
$result = $this->_apply_plugin_action((!empty($query['multisite']) && (bool) $query['multisite']) ? 'network_activate' : 'activate', $query);
|
||||
if (empty($result['activated'])) {
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download, install the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the plugin name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function install_plugin($query) {
|
||||
|
||||
$fields = array('plugin', 'slug');
|
||||
$permissions = array('install_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_plugin_action('install', $query);
|
||||
if (empty($result['installed'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall/delete the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the plugin name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function delete_plugin($query) {
|
||||
|
||||
$fields = array('plugin');
|
||||
$permissions = array('delete_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$info = $this->_get_plugin_info($query);
|
||||
if ($info['installed']) {
|
||||
// Deactivate first before delete to invalidate the activate
|
||||
// state/status prior to deleting the item. Otherwise, WordPress will keep
|
||||
// that state, and as soon as you install the same plugin it will be automatically
|
||||
// activated since it's previous state was kept.
|
||||
deactivate_plugins($info['plugin_path']);
|
||||
|
||||
$deleted = delete_plugins(array($info['plugin_path']));
|
||||
if ($deleted) {
|
||||
$result = array('deleted' => true, 'info' => $this->_get_plugin_info($query), 'last_state' => $info);
|
||||
} else {
|
||||
return $this->_generic_error_response('delete_plugin_failed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'delete_plugin_failed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return $this->_generic_error_response('plugin_not_installed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'plugin_not_installed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates/upgrade the plugin
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the plugin name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function update_plugin($query) {
|
||||
|
||||
$fields = array('plugin', 'slug');
|
||||
$permissions = array('update_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
// Make sure that we still have the plugin installed before running
|
||||
// the update process
|
||||
$info = $this->_get_plugin_info($query);
|
||||
if ($info['installed']) {
|
||||
// Load the updates command class if not existed
|
||||
if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
|
||||
$update_command = new UpdraftCentral_Updates_Commands($this->rc);
|
||||
|
||||
$result = $update_command->update_plugin($info['plugin_path'], $query['slug']);
|
||||
if (!empty($result['error'])) {
|
||||
$result['values'] = array('plugin' => $query['plugin'], 'info' => $info);
|
||||
}
|
||||
} else {
|
||||
return $this->_generic_error_response('plugin_not_installed', array(
|
||||
'plugin' => $query['plugin'],
|
||||
'error_code' => 'plugin_not_installed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin information along with its active and install status
|
||||
*
|
||||
* @internal
|
||||
* @param array $query Contains either the plugin name or slug or both to be used when retrieving information
|
||||
* @return array
|
||||
*/
|
||||
private function _get_plugin_info($query) {
|
||||
|
||||
$info = array(
|
||||
'active' => false,
|
||||
'installed' => false
|
||||
);
|
||||
|
||||
// Clear plugin cache so that newly installed/downloaded plugins
|
||||
// gets reflected when calling "get_plugins"
|
||||
if (function_exists('wp_clean_plugins_cache')) {
|
||||
wp_clean_plugins_cache();
|
||||
}
|
||||
|
||||
// Gets all plugins available.
|
||||
$get_plugins = get_plugins();
|
||||
|
||||
// Loops around each plugin available.
|
||||
foreach ($get_plugins as $key => $value) {
|
||||
$slug = $this->extract_slug_from_info($key, $value);
|
||||
|
||||
// If the plugin name matches that of the specified name, it will gather details.
|
||||
// In case name check isn't enough, we'll use slug to verify if the plugin being queried is actually installed.
|
||||
//
|
||||
// Reason for name check failure:
|
||||
// Due to plugin name inconsistencies - where wordpress.org registered plugin name is different
|
||||
// from the actual plugin files's metadata (found inside the plugin's PHP file itself).
|
||||
if ((!empty($query['plugin']) && html_entity_decode($value['Name']) === html_entity_decode($query['plugin'])) || (!empty($query['slug']) && $slug === $query['slug'])) {
|
||||
$info['installed'] = true;
|
||||
$info['active'] = is_plugin_active($key);
|
||||
$info['plugin_path'] = $key;
|
||||
$info['data'] = $value;
|
||||
$info['name'] = $value['Name'];
|
||||
$info['slug'] = $slug;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the slug from the plugin data
|
||||
*
|
||||
* @param string $key They key of the current info
|
||||
* @param array $info Data pulled from the plugin file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function extract_slug_from_info($key, $info) {
|
||||
if (!is_array($info) || empty($info) || empty($key)) return '';
|
||||
|
||||
$temp = explode('/', $key);
|
||||
|
||||
// With WP standards textdomain must always be equal to the plugin's folder name
|
||||
// but for premium plugins this may not always be the case thus, we extract the folder
|
||||
// name from the key as the default slug.
|
||||
$slug = basename($temp[0], '.php');
|
||||
|
||||
if (!empty($info['TextDomain']) && 1 === count($temp)) {
|
||||
// For plugin without folder we compare the extracted slug with the 'TextDomain'
|
||||
// and if they're not equal then 'TextDomain' will assume as slug.
|
||||
if ($slug != $info['TextDomain']) $slug = $info['TextDomain'];
|
||||
}
|
||||
|
||||
// If in case the user kept the hello-dolly plugin then we'll make sure that it gets
|
||||
// the proper slug for it, otherwise, we'll end up with the wrong slug 'hello' instead of
|
||||
// 'hello-dolly'. Wrong slug will produce error in UpdraftCentral when running it against
|
||||
// wordpress.org for further information retrieval.
|
||||
$slug = ('Hello Dolly' === $info['Name']) ? 'hello-dolly' : $slug;
|
||||
|
||||
return $slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all available plugins with additional attributes and settings needed by UpdraftCentral
|
||||
*
|
||||
* @param array $query Parameter array Any available parameters needed for this action
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function load_plugins($query) {
|
||||
|
||||
$permissions = array('install_plugins', 'activate_plugins');
|
||||
if (is_multisite() && !is_super_admin(get_current_user_id())) $permissions = array('activate_plugins');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, array(), $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$website = get_bloginfo('name');
|
||||
$results = array();
|
||||
|
||||
// Load the updates command class if not existed
|
||||
if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
|
||||
$updates = new UpdraftCentral_Updates_Commands($this->rc);
|
||||
|
||||
// Get plugins for update
|
||||
$plugin_updates = $updates->get_item_updates('plugins');
|
||||
|
||||
// Get all plugins
|
||||
$plugins = get_plugins();
|
||||
|
||||
if (is_multisite() && !is_super_admin(get_current_user_id())) {
|
||||
|
||||
// If the "Plugins" menu is disabled for the subsites on a multisite
|
||||
// network then we return an empty "plugins" array.
|
||||
$menu_items = get_site_option('menu_items');
|
||||
if (empty($menu_items) || !isset($menu_items['plugins'])) {
|
||||
$plugins = array();
|
||||
} else {
|
||||
$show_network_active = apply_filters('show_network_active_plugins', current_user_can('manage_network_plugins'));
|
||||
|
||||
$filtered_plugins = array();
|
||||
foreach ($plugins as $file => $data) {
|
||||
if (is_network_only_plugin($file) && !is_plugin_active($file)) {
|
||||
if ($show_network_active) $filtered_plugins[$file] = $data;
|
||||
} elseif (is_plugin_active_for_network($file)) {
|
||||
if ($show_network_active) $filtered_plugins[$file] = $data;
|
||||
} else {
|
||||
$filtered_plugins[$file] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
$plugins = $filtered_plugins;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($plugins as $key => $value) {
|
||||
$slug = $this->extract_slug_from_info($key, $value);
|
||||
|
||||
$plugin = new stdClass();
|
||||
$plugin->name = $value['Name'];
|
||||
$plugin->description = $value['Description'];
|
||||
$plugin->slug = $slug;
|
||||
$plugin->version = $value['Version'];
|
||||
$plugin->author = $value['Author'];
|
||||
$plugin->status = is_plugin_active($key) ? 'active' : 'inactive';
|
||||
$plugin->website = $website;
|
||||
$plugin->multisite = is_multisite();
|
||||
$plugin->site_url = trailingslashit(get_bloginfo('url'));
|
||||
|
||||
if (!empty($plugin_updates[$key])) {
|
||||
$update_info = $plugin_updates[$key];
|
||||
|
||||
if (version_compare($update_info->Version, $update_info->update->new_version, '<')) {
|
||||
if (!empty($update_info->update->new_version)) $plugin->latest_version = $update_info->update->new_version;
|
||||
if (!empty($update_info->update->package)) $plugin->download_link = $update_info->update->package;
|
||||
if (!empty($update_info->update->sections)) $plugin->sections = $update_info->update->sections;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($plugin->short_description) && !empty($plugin->description)) {
|
||||
// Only pull the first sentence as short description, it should be enough rather than displaying
|
||||
// an empty description or a full blown one which the user can access anytime if they press on
|
||||
// the view details link in UpdraftCentral.
|
||||
$temp = explode('.', $plugin->description);
|
||||
$short_description = $temp[0];
|
||||
|
||||
// Adding the second sentence wouldn't hurt, in case the first sentence is too short.
|
||||
if (isset($temp[1])) $short_description .= '.'.$temp[1];
|
||||
|
||||
$plugin->short_description = $short_description.'.';
|
||||
}
|
||||
|
||||
$results[] = $plugin;
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'plugins' => $results,
|
||||
'is_super_admin' => is_super_admin(),
|
||||
);
|
||||
|
||||
$result = array_merge($result, $this->_get_backup_credentials_settings(WP_PLUGIN_DIR));
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the backup and security credentials settings for this website
|
||||
*
|
||||
* @param array $query Parameter array Any available parameters needed for this action
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function get_plugin_requirements() {
|
||||
return $this->_response($this->_get_backup_credentials_settings(WP_PLUGIN_DIR));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,721 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles UpdraftCentral Theme Commands which basically handles
|
||||
* the installation and activation of a theme
|
||||
*/
|
||||
class UpdraftCentral_Theme_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
private $switched = false;
|
||||
|
||||
/**
|
||||
* Function that gets called before every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _pre_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- This function is called from listener.php and $extra_info is being sent.
|
||||
// Here we assign the current blog_id to a variable $blog_id
|
||||
$blog_id = get_current_blog_id();
|
||||
if (!empty($data['site_id'])) $blog_id = $data['site_id'];
|
||||
|
||||
if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
|
||||
$this->switched = switch_to_blog($blog_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that gets called after every action
|
||||
*
|
||||
* @param string $command a string that corresponds to UDC command to call a certain method for this class.
|
||||
* @param array $data an array of data post or get fields
|
||||
* @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
|
||||
*
|
||||
* link to udrpc_action main function in class UpdraftCentral_Listener
|
||||
*/
|
||||
public function _post_action($command, $data, $extra_info) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Unused parameter is present because the caller from UpdraftCentral_Listener class uses 3 arguments.
|
||||
// Here, we're restoring to the current (default) blog before we switched
|
||||
if ($this->switched) restore_current_blog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_admin_include('theme.php', 'file.php', 'template.php', 'class-wp-upgrader.php', 'theme-install.php', 'update.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs and activates a theme through upload
|
||||
*
|
||||
* @param array $params Parameter array containing information pertaining the currently uploaded theme
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function upload_theme($params) {
|
||||
return $this->process_chunk_upload($params, 'theme');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the theme is currently installed and activated.
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the theme to check
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function is_theme_installed($query) {
|
||||
|
||||
if (!isset($query['theme']))
|
||||
return $this->_generic_error_response('theme_name_required');
|
||||
|
||||
|
||||
$result = $this->_get_theme_info($query['theme']);
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies currently requested action for theme processing
|
||||
*
|
||||
* @param string $action The action to apply (e.g. activate or install)
|
||||
* @param array $query Parameter array containing information for the currently requested action
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _apply_theme_action($action, $query) {
|
||||
|
||||
$result = array();
|
||||
switch ($action) {
|
||||
case 'activate':
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if ($info['installed']) {
|
||||
switch_theme($info['slug']);
|
||||
if (wp_get_theme()->get_stylesheet() === $info['slug']) {
|
||||
$result = array('activated' => true, 'info' => $this->_get_theme_info($query['theme']), 'last_state' => $info);
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_activated', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_activated',
|
||||
'error_message' => __('There appears to be a problem activating or switching to the intended theme.', 'updraftplus').' '.__('Please check your permissions and try again.', 'updraftplus'),
|
||||
'info' => $this->_get_theme_info($query['theme'])
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_installed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'error_message' => __('The theme you wish to activate is either not installed or has been removed recently.', 'updraftplus'),
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 'network_enable':
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if ($info['installed']) {
|
||||
if (current_user_can('manage_network_themes')) {
|
||||
// Make sure that network_enable_theme is present and callable since
|
||||
// it is only available at 4.6. If not, we'll do things the old fashion way
|
||||
if (is_callable(array('WP_Theme', 'network_enable_theme'))) {
|
||||
WP_Theme::network_enable_theme($info['slug']);
|
||||
} else {
|
||||
$allowed_themes = get_site_option('allowedthemes');
|
||||
$allowed_themes[$info['slug']] = true;
|
||||
|
||||
update_site_option('allowedthemes', $allowed_themes);
|
||||
}
|
||||
}
|
||||
|
||||
$allowed = WP_Theme::get_allowed_on_network();
|
||||
if (is_array($allowed) && !empty($allowed[$info['slug']])) {
|
||||
$result = array('enabled' => true, 'info' => $this->_get_theme_info($query['theme']), 'last_state' => $info);
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_enabled', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_enabled',
|
||||
'error_message' => __('There appears to be a problem enabling the intended theme on your network.', 'updraftplus').' '.__('Please kindly check your permission and try again.', 'updraftplus'),
|
||||
'info' => $this->_get_theme_info($query['theme'])
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_installed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'error_message' => __('The theme you wish to enable on your network is either not installed or has been removed recently.', 'updraftplus'),
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 'network_disable':
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if ($info['installed']) {
|
||||
if (current_user_can('manage_network_themes')) {
|
||||
// Make sure that network_disable_theme is present and callable since
|
||||
// it is only available at 4.6. If not, we'll do things the old fashion way
|
||||
if (is_callable(array('WP_Theme', 'network_disable_theme'))) {
|
||||
WP_Theme::network_disable_theme($info['slug']);
|
||||
} else {
|
||||
$allowed_themes = get_site_option('allowedthemes');
|
||||
if (isset($allowed_themes[$info['slug']])) {
|
||||
unset($allowed_themes[$info['slug']]);
|
||||
}
|
||||
|
||||
update_site_option('allowedthemes', $allowed_themes);
|
||||
}
|
||||
}
|
||||
|
||||
$allowed = WP_Theme::get_allowed_on_network();
|
||||
if (is_array($allowed) && empty($allowed[$info['slug']])) {
|
||||
$result = array('disabled' => true, 'info' => $this->_get_theme_info($query['theme']), 'last_state' => $info);
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_disabled', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_disabled',
|
||||
'error_message' => __('There appears to be a problem disabling the intended theme from your network.', 'updraftplus').' '.__('Please kindly check your permission and try again.', 'updraftplus'),
|
||||
'info' => $this->_get_theme_info($query['theme'])
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$result = $this->_generic_error_response('theme_not_installed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'error_message' => __('The theme you wish to disable from your network is either not installed or has been removed recently.', 'updraftplus'),
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 'install':
|
||||
$api = themes_api('theme_information', array(
|
||||
'slug' => $query['slug'],
|
||||
'fields' => array(
|
||||
'description' => true,
|
||||
'sections' => false,
|
||||
'rating' => true,
|
||||
'ratings' => true,
|
||||
'downloaded' => true,
|
||||
'downloadlink' => true,
|
||||
'last_updated' => true,
|
||||
'screenshot_url' => true,
|
||||
'parent' => true,
|
||||
)
|
||||
));
|
||||
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if (is_wp_error($api)) {
|
||||
$result = $this->_generic_error_response('generic_response_error', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'error_message' => $api->get_error_message(),
|
||||
'info' => $info
|
||||
));
|
||||
} else {
|
||||
$installed = $info['installed'];
|
||||
|
||||
$error_code = $error_message = '';
|
||||
if (!$installed) {
|
||||
// WP < 3.7
|
||||
if (!class_exists('Automatic_Upgrader_Skin')) include_once(dirname(dirname(__FILE__)).'/classes/class-automatic-upgrader-skin.php');
|
||||
|
||||
$skin = new Automatic_Upgrader_Skin();
|
||||
$upgrader = new Theme_Upgrader($skin);
|
||||
|
||||
$download_link = $api->download_link;
|
||||
$installed = $upgrader->install($download_link);
|
||||
|
||||
if (is_wp_error($installed)) {
|
||||
$error_code = $installed->get_error_code();
|
||||
$error_message = $installed->get_error_message();
|
||||
} elseif (is_wp_error($skin->result)) {
|
||||
$error_code = $skin->result->get_error_code();
|
||||
$error_message = $skin->result->get_error_message();
|
||||
|
||||
$error_data = $skin->result->get_error_data($error_code);
|
||||
if (!empty($error_data)) {
|
||||
if (is_array($error_data)) $error_data = json_encode($error_data);
|
||||
$error_message .= ' '.$error_data;
|
||||
}
|
||||
} elseif (is_null($installed) || !$installed) {
|
||||
global $wp_filesystem;
|
||||
$upgrade_messages = $skin->get_upgrade_messages();
|
||||
|
||||
if (!class_exists('WP_Filesystem_Base')) include_once(ABSPATH.'/wp-admin/includes/class-wp-filesystem-base.php');
|
||||
|
||||
// Pass through the error from WP_Filesystem if one was raised.
|
||||
if ($wp_filesystem instanceof WP_Filesystem_Base && is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
|
||||
$error_code = $wp_filesystem->errors->get_error_code();
|
||||
$error_message = $wp_filesystem->errors->get_error_message();
|
||||
} elseif (!empty($upgrade_messages)) {
|
||||
// We're only after for the last feedback that we received from the install process. Mostly,
|
||||
// that is where the last error has been inserted.
|
||||
$messages = $skin->get_upgrade_messages();
|
||||
$error_code = 'install_failed';
|
||||
$error_message = end($messages);
|
||||
} else {
|
||||
$error_code = 'unable_to_connect_to_filesystem';
|
||||
$error_message = __('Unable to connect to the filesystem.', 'updraftplus').' '.__('Please confirm your credentials.', 'updraftplus');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$installed || is_wp_error($installed)) {
|
||||
$result = $this->_generic_error_response('theme_install_failed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => $error_code,
|
||||
'error_message' => $error_message,
|
||||
'info' => $this->_get_theme_info($query['theme'])
|
||||
));
|
||||
} else {
|
||||
$result = array('installed' => true, 'info' => $this->_get_theme_info($query['theme']), 'last_state' => $info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the submitted credentials to the global $_POST variable
|
||||
*
|
||||
* @param array $query Parameter array containing information for the currently requested action
|
||||
*/
|
||||
private function _preload_credentials($query) {
|
||||
if (!empty($query) && isset($query['filesystem_credentials'])) {
|
||||
parse_str($query['filesystem_credentials'], $filesystem_credentials);
|
||||
if (is_array($filesystem_credentials)) {
|
||||
foreach ($filesystem_credentials as $key => $value) {
|
||||
// Put them into $_POST, which is where request_filesystem_credentials() checks for them.
|
||||
$_POST[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we have the required fields submitted and the user has
|
||||
* the capabilities to execute the requested action
|
||||
*
|
||||
* @param array $query The submitted information
|
||||
* @param array $fields The required fields to check
|
||||
* @param array $capabilities The capabilities to check and validate
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function _validate_fields_and_capabilities($query, $fields, $capabilities) {
|
||||
|
||||
$error = '';
|
||||
if (!empty($fields)) {
|
||||
for ($i=0; $i<count($fields); $i++) {
|
||||
$field = $fields[$i];
|
||||
|
||||
if (!isset($query[$field])) {
|
||||
if ('keyword' === $field) {
|
||||
$error = $this->_generic_error_response('keyword_required');
|
||||
} else {
|
||||
$error = $this->_generic_error_response('theme_'.$query[$field].'_required');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($error) && !empty($capabilities)) {
|
||||
for ($i=0; $i<count($capabilities); $i++) {
|
||||
if (!current_user_can($capabilities[$i])) {
|
||||
$error = $this->_generic_error_response('theme_insufficient_permission');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing an action for multiple items
|
||||
*
|
||||
* @param array $query Parameter array containing a list of themes to process
|
||||
* @return array Contains the results of the bulk process
|
||||
*/
|
||||
public function process_action_in_bulk($query) {
|
||||
$action = isset($query['action']) ? $query['action'] : '';
|
||||
$items = isset($query['args']) ? $query['args']['items'] : array();
|
||||
|
||||
$results = array();
|
||||
if (!empty($action) && !empty($items) && is_array($items)) {
|
||||
foreach ($items as $value) {
|
||||
if (method_exists($this, $action)) {
|
||||
$results[] = $this->$action($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_response($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the theme
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the theme to activate
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function activate_theme($query) {
|
||||
|
||||
$fields = array('theme');
|
||||
$permissions = array('switch_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_theme_action('activate', $query);
|
||||
if (empty($result['activated'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables theme for network
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the theme to activate
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function network_enable_theme($query) {
|
||||
|
||||
$fields = array('theme');
|
||||
$permissions = array('switch_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_theme_action('network_enable', $query);
|
||||
if (empty($result['enabled'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables theme from network
|
||||
*
|
||||
* @param array $query Parameter array containing the name of the theme to activate
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function network_disable_theme($query) {
|
||||
|
||||
$fields = array('theme');
|
||||
$permissions = array('switch_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_theme_action('network_disable', $query);
|
||||
if (empty($result['disabled'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download, install and activates the theme
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function install_activate_theme($query) {
|
||||
|
||||
$fields = array('theme', 'slug');
|
||||
$permissions = array('install_themes', 'switch_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_theme_action('install', $query);
|
||||
if (!empty($result['installed']) && $result['installed']) {
|
||||
$result = $this->_apply_theme_action('activate', $query);
|
||||
if (empty($result['activated'])) {
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download, install the theme
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function install_theme($query) {
|
||||
|
||||
$fields = array('theme', 'slug');
|
||||
$permissions = array('install_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$result = $this->_apply_theme_action('install', $query);
|
||||
if (empty($result['installed'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall/delete the theme
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function delete_theme($query) {
|
||||
|
||||
$fields = array('theme');
|
||||
$permissions = array('delete_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if ($info['installed']) {
|
||||
$deleted = delete_theme($info['slug']);
|
||||
|
||||
if ($deleted) {
|
||||
$result = array('deleted' => true, 'info' => $this->_get_theme_info($query['theme']), 'last_state' => $info);
|
||||
} else {
|
||||
return $this->_generic_error_response('delete_theme_failed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'delete_theme_failed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return $this->_generic_error_response('theme_not_installed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates/upgrade the theme
|
||||
*
|
||||
* @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function update_theme($query) {
|
||||
|
||||
$fields = array('theme');
|
||||
$permissions = array('update_themes');
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, $fields, $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$this->_preload_credentials($query);
|
||||
|
||||
// Make sure that we still have the theme installed before running
|
||||
// the update process
|
||||
$info = $this->_get_theme_info($query['theme']);
|
||||
if ($info['installed']) {
|
||||
// Load the updates command class if not existed
|
||||
if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
|
||||
$update_command = new UpdraftCentral_Updates_Commands($this->rc);
|
||||
|
||||
$result = $update_command->update_theme($info['slug']);
|
||||
if (!empty($result['error'])) {
|
||||
$result['values'] = array('theme' => $query['theme'], 'info' => $info);
|
||||
}
|
||||
} else {
|
||||
return $this->_generic_error_response('theme_not_installed', array(
|
||||
'theme' => $query['theme'],
|
||||
'error_code' => 'theme_not_installed',
|
||||
'info' => $info
|
||||
));
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the theme information along with its active and install status
|
||||
*
|
||||
* @internal
|
||||
* @param array $theme The name of the theme to pull the information from
|
||||
* @return array Contains the theme information
|
||||
*/
|
||||
private function _get_theme_info($theme) {
|
||||
|
||||
$info = array(
|
||||
'active' => false,
|
||||
'installed' => false
|
||||
);
|
||||
|
||||
// Clear theme cache so that newly installed/downloaded themes
|
||||
// gets reflected when calling "get_themes"
|
||||
if (function_exists('wp_clean_themes_cache')) {
|
||||
wp_clean_themes_cache();
|
||||
}
|
||||
|
||||
// Gets all themes available.
|
||||
$themes = wp_get_themes();
|
||||
$current_theme_slug = basename(get_stylesheet_directory());
|
||||
|
||||
// Loops around each theme available.
|
||||
foreach ($themes as $slug => $value) {
|
||||
$name = $value->get('Name');
|
||||
$theme_name = !empty($name) ? $name : $slug;
|
||||
|
||||
// If the theme name matches that of the specified name, it will gather details.
|
||||
if ($theme_name === $theme) {
|
||||
$info['installed'] = true;
|
||||
$info['active'] = ($slug === $current_theme_slug) ? true : false;
|
||||
$info['slug'] = $slug;
|
||||
$info['data'] = $value;
|
||||
$info['name'] = $theme_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all available themes with additional attributes and settings needed by UpdraftCentral
|
||||
*
|
||||
* @param array $query Parameter array Any available parameters needed for this action
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function load_themes($query) {
|
||||
|
||||
$permissions = array('install_themes', 'switch_themes');
|
||||
$args = array();
|
||||
if (is_multisite() && !is_super_admin(get_current_user_id())) {
|
||||
$permissions = array('switch_themes');
|
||||
$args = array('allowed' => true, 'blog_id' => get_current_blog_id());
|
||||
}
|
||||
|
||||
$error = $this->_validate_fields_and_capabilities($query, array(), $permissions);
|
||||
if (!empty($error)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$website = get_bloginfo('name');
|
||||
$results = array();
|
||||
|
||||
// Load the updates command class if not existed
|
||||
if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
|
||||
$updates = new UpdraftCentral_Updates_Commands($this->rc);
|
||||
|
||||
// Get themes for update
|
||||
$theme_updates = (array) $updates->get_item_updates('themes');
|
||||
|
||||
// Get all themes
|
||||
$themes = wp_get_themes($args);
|
||||
$current_theme_slug = basename(get_stylesheet_directory());
|
||||
|
||||
foreach ($themes as $slug => $value) {
|
||||
$name = $value->get('Name');
|
||||
$theme_name = !empty($name) ? $name : $slug;
|
||||
|
||||
$theme = new stdClass();
|
||||
$theme->name = $theme_name;
|
||||
$theme->description = $value->get('Description');
|
||||
$theme->slug = $slug;
|
||||
$theme->version = $value->get('Version');
|
||||
$theme->author = $value->get('Author');
|
||||
$theme->status = ($slug === $current_theme_slug) ? 'active' : 'inactive';
|
||||
|
||||
$template = $value->get('Template');
|
||||
$theme->child_theme = !empty($template) ? true : false;
|
||||
$theme->website = $website;
|
||||
$theme->multisite = is_multisite();
|
||||
$theme->site_url = trailingslashit(get_bloginfo('url'));
|
||||
|
||||
if ($theme->child_theme) {
|
||||
$parent_theme = wp_get_theme($template);
|
||||
$parent_name = $parent_theme->get('Name');
|
||||
|
||||
$theme->parent = !empty($parent_name) ? $parent_name : $parent_theme->get_stylesheet();
|
||||
}
|
||||
|
||||
if (!empty($theme_updates[$slug])) {
|
||||
$update_info = $theme_updates[$slug];
|
||||
|
||||
if (version_compare($theme->version, $update_info->update['new_version'], '<')) {
|
||||
if (!empty($update_info->update['new_version'])) $theme->latest_version = $update_info->update['new_version'];
|
||||
if (!empty($update_info->update['package'])) $theme->download_link = $update_info->update['package'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($theme->short_description) && !empty($theme->description)) {
|
||||
// Only pull the first sentence as short description, it should be enough rather than displaying
|
||||
// an empty description or a full blown one which the user can access anytime if they press on
|
||||
// the view details link in UpdraftCentral.
|
||||
$temp = explode('.', $theme->description);
|
||||
$short_description = $temp[0];
|
||||
|
||||
// Adding the second sentence wouldn't hurt, in case the first sentence is too short.
|
||||
if (isset($temp[1])) $short_description .= '.'.$temp[1];
|
||||
|
||||
$theme->short_description = $short_description.'.';
|
||||
}
|
||||
|
||||
$results[] = $theme;
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'themes' => $results,
|
||||
'theme_updates' => $theme_updates,
|
||||
'is_super_admin' => is_super_admin(),
|
||||
);
|
||||
|
||||
$result = array_merge($result, $this->_get_backup_credentials_settings(get_theme_root()));
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the backup and security credentials settings for this website
|
||||
*
|
||||
* @param array $query Parameter array Any available parameters needed for this action
|
||||
* @return array Contains the result of the current process
|
||||
*/
|
||||
public function get_theme_requirements() {
|
||||
return $this->_response($this->_get_backup_credentials_settings(get_theme_root()));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,632 @@
|
||||
<?php
|
||||
|
||||
if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
|
||||
|
||||
/**
|
||||
* Handles Users Commands
|
||||
*/
|
||||
class UpdraftCentral_Users_Commands extends UpdraftCentral_Commands {
|
||||
|
||||
/**
|
||||
* Compares two user object whether one is lesser than, equal to, greater than the other
|
||||
*
|
||||
* @internal
|
||||
* @param array $a First user in the comparison
|
||||
* @param array $b Second user in the comparison
|
||||
* @return integer Comparison results (0 = equal, -1 = less than, 1 = greater than)
|
||||
*/
|
||||
private function compare_user_id($a, $b) {
|
||||
if ($a->ID === $b->ID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($a->ID < $b->ID) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches users based from the keyword submitted
|
||||
*
|
||||
* @internal
|
||||
* @param array $query Parameter array containing the filter and keyword fields
|
||||
* @return array Contains the list of users found as well as the total users count
|
||||
*/
|
||||
private function _search_users($query) {
|
||||
$this->_admin_include('user.php');
|
||||
$query1 = new WP_User_Query(array(
|
||||
'orderby' => 'ID',
|
||||
'order' => 'ASC',
|
||||
'role'=> $query["role"],
|
||||
'search' => '*' . esc_attr($query["search"]) . '*',
|
||||
'search_columns' => array('user_login', 'user_email')
|
||||
));
|
||||
$query2 = new WP_User_Query(array(
|
||||
'orderby' => 'ID',
|
||||
'order' => 'ASC',
|
||||
'role'=> $query["role"],
|
||||
'meta_query'=>array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'first_name',
|
||||
'value' => $query["search"],
|
||||
'compare' => 'LIKE'
|
||||
),
|
||||
array(
|
||||
'key' => 'last_name',
|
||||
'value' => $query["search"],
|
||||
'compare' => 'LIKE'
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
if (empty($query1->results) && empty($query2->results)) {
|
||||
return array("message" => "users_not_found");
|
||||
} else {
|
||||
$found_users = array_merge($query1->results, $query2->results);
|
||||
$temp = array();
|
||||
foreach ($found_users as $new_user) {
|
||||
if (!isset($temp[$new_user->ID])) {
|
||||
$temp[$new_user->ID] = $new_user;
|
||||
}
|
||||
};
|
||||
|
||||
$users = array_values($temp);
|
||||
|
||||
// Sort users:
|
||||
usort($users, array($this, 'compare_user_id'));
|
||||
$offset = ((int) $query['page_no'] * (int) $query['per_page']) - (int) $query['per_page'];
|
||||
$user_list = array_slice($users, $offset, $query['per_page']);
|
||||
|
||||
return array(
|
||||
'users' => $user_list,
|
||||
'total_users' => count($users)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of pages needed to construct the pagination links
|
||||
*
|
||||
* @internal
|
||||
* @param array $query
|
||||
* @param array $total_users The total number of users found from the WP_User_Query query
|
||||
* @return array Contains information needed to construct the pagination links
|
||||
*/
|
||||
private function _calculate_pages($query, $total_users) {
|
||||
|
||||
$per_page_options = array(10, 20, 30, 40, 50);
|
||||
|
||||
if (!empty($query)) {
|
||||
|
||||
$pages = array();
|
||||
$page_count = ceil($total_users / $query["per_page"]);
|
||||
if ($page_count > 1) {
|
||||
|
||||
for ($i = 0; $i < $page_count; $i++) {
|
||||
if ($i + 1 == $query['page_no']) {
|
||||
$paginator_item = array(
|
||||
"value"=>$i+1,
|
||||
"setting"=>"disabled"
|
||||
);
|
||||
} else {
|
||||
$paginator_item = array(
|
||||
"value"=>$i+1
|
||||
);
|
||||
}
|
||||
array_push($pages, $paginator_item);
|
||||
};
|
||||
|
||||
if ($query['page_no'] >= $page_count) {
|
||||
$page_next = array(
|
||||
"value"=>$page_count,
|
||||
"setting"=>"disabled"
|
||||
);
|
||||
} else {
|
||||
$page_next = array(
|
||||
"value"=>$query['page_no'] + 1
|
||||
);
|
||||
};
|
||||
if (1 === $query['page_no']) {
|
||||
$page_prev = array(
|
||||
"value"=>1,
|
||||
"setting"=>"disabled"
|
||||
);
|
||||
} else {
|
||||
$page_prev = array(
|
||||
"value"=>$query['page_no'] - 1
|
||||
);
|
||||
};
|
||||
|
||||
return array(
|
||||
"page_no" => $query['page_no'],
|
||||
"per_page" => $query["per_page"],
|
||||
"page_count" => $page_count,
|
||||
"pages" => $pages,
|
||||
"page_next" => $page_next,
|
||||
"page_prev" => $page_prev,
|
||||
"total_results" => $total_users,
|
||||
"per_page_options" => $per_page_options
|
||||
);
|
||||
|
||||
} else {
|
||||
return array(
|
||||
"page_no" => $query['page_no'],
|
||||
"per_page" => $query["per_page"],
|
||||
"page_count" => $page_count,
|
||||
"total_results" => $total_users,
|
||||
"per_page_options" => $per_page_options
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return array(
|
||||
"per_page_options" => $per_page_options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether the username exists
|
||||
*
|
||||
* @param array $params Contains the user name to check and validate
|
||||
* @return array An array containing the result of the current process
|
||||
*/
|
||||
public function check_username($params) {
|
||||
$this->_admin_include('user.php');
|
||||
$username = $params['user_name'];
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (!empty($params['site_id'])) {
|
||||
$blog_id = $params['site_id'];
|
||||
}
|
||||
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull users from.
|
||||
|
||||
$switched = function_exists('switch_to_blog') ? switch_to_blog($blog_id) : false;
|
||||
|
||||
if (username_exists($username) && is_user_member_of_blog(username_exists($username), $blog_id)) {
|
||||
$result = array("valid" => false, "message" => 'username_exists');
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (!validate_username($username)) {
|
||||
$result = array("valid" => false, "message" => 'username_invalid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
$result = array("valid" => true, "message" => 'username_valid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls blog sites available
|
||||
* for the current WP instance.
|
||||
* If the site is a multisite, then sites under the network
|
||||
* will be pulled, otherwise, it will return an empty array.
|
||||
*
|
||||
* @return Array - an array of sites
|
||||
*/
|
||||
private function _get_blog_sites() {
|
||||
|
||||
if (!is_multisite()) return array();
|
||||
|
||||
// Initialize array container
|
||||
$sites = $network_sites = array();
|
||||
|
||||
// Check to see if latest get_sites (available on WP version >= 4.6) function is
|
||||
// available to pull any available sites from the current WP instance. If not, then
|
||||
// we're going to use the fallback function wp_get_sites (for older version).
|
||||
if (function_exists('get_sites') && class_exists('WP_Site_Query')) {
|
||||
$network_sites = get_sites();
|
||||
} else {
|
||||
if (function_exists('wp_get_sites')) {
|
||||
$network_sites = wp_get_sites();
|
||||
}
|
||||
}
|
||||
|
||||
// We only process if sites array is not empty, otherwise, bypass
|
||||
// the next block.
|
||||
if (!empty($network_sites)) {
|
||||
foreach ($network_sites as $site) {
|
||||
|
||||
// Here we're checking if the site type is an array, because
|
||||
// we're pulling the blog_id property based on the type of
|
||||
// site returned.
|
||||
// get_sites returns an array of object, whereas the wp_get_sites
|
||||
// function returns an array of array.
|
||||
$blog_id = is_array($site) ? $site['blog_id'] : $site->blog_id;
|
||||
|
||||
|
||||
// We're saving the blog_id and blog name as an associative item
|
||||
// into the sites array, that will be used as "Sites" option in
|
||||
// the frontend.
|
||||
$sites[$blog_id] = get_blog_details($blog_id)->blogname;
|
||||
}
|
||||
}
|
||||
|
||||
return $sites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether the email exists
|
||||
*
|
||||
* @param array $params Contains the email to check and validate
|
||||
* @return array An array containing the result of the current process
|
||||
*/
|
||||
public function check_email($params) {
|
||||
$this->_admin_include('user.php');
|
||||
$email = $params['email'];
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['site_id']) && 0 !== $params['site_id']) {
|
||||
$blog_id = $params['site_id'];
|
||||
}
|
||||
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull users from.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
if (is_email($email) === false) {
|
||||
$result = array("valid" => false, "message" => 'email_invalid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
if (email_exists($email) && is_user_member_of_blog(email_exists($email), $blog_id)) {
|
||||
$result = array("valid" => false, "message" => 'email_exists');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
$result = array("valid" => true, "message" => 'email_valid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_users function pull all the users from the database
|
||||
* based on the current search parameters/filters. Please see _search_users
|
||||
* for the breakdown of these parameters.
|
||||
*
|
||||
* @param array $query Parameter array containing the filter and keyword fields
|
||||
* @return array An array containing the result of the current process
|
||||
*/
|
||||
public function get_users($query) {
|
||||
$this->_admin_include('user.php');
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($query['site_id']) && 0 !== $query['site_id']) $blog_id = $query['site_id'];
|
||||
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull users from.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
// Set default:
|
||||
if (empty($query["per_page"])) {
|
||||
$query["per_page"] = 10;
|
||||
}
|
||||
if (empty($query['page_no'])) {
|
||||
$query['page_no'] = 1;
|
||||
}
|
||||
if (empty($query["role"])) {
|
||||
$query["role"] = "";
|
||||
}
|
||||
|
||||
$users = array();
|
||||
$total_users = 0;
|
||||
|
||||
if (!empty($query["search"])) {
|
||||
$search_results = $this->_search_users($query);
|
||||
|
||||
if (isset($search_results['users'])) {
|
||||
$users = $search_results['users'];
|
||||
$total_users = $search_results['total_users'];
|
||||
}
|
||||
} else {
|
||||
$user_query = new WP_User_Query(array(
|
||||
'orderby' => 'ID',
|
||||
'order' => 'ASC',
|
||||
'number' => $query["per_page"],
|
||||
'paged'=> $query['page_no'],
|
||||
'role'=> $query["role"]
|
||||
));
|
||||
|
||||
if (empty($user_query->results)) {
|
||||
$result = array("message" => 'users_not_found');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
$users = $user_query->results;
|
||||
$total_users = $user_query->get_total();
|
||||
}
|
||||
|
||||
foreach ($users as &$user) {
|
||||
$user_object = get_userdata($user->ID);
|
||||
if (method_exists($user_object, 'to_array')) {
|
||||
$user = $user_object->to_array();
|
||||
$user["roles"] = $user_object->roles;
|
||||
$user["first_name"] = $user_object->first_name;
|
||||
$user["last_name"] = $user_object->last_name;
|
||||
$user["description"] = $user_object->description;
|
||||
} else {
|
||||
$user = $user_object;
|
||||
}
|
||||
}
|
||||
|
||||
$result = array(
|
||||
"users"=>$users,
|
||||
"paging" => $this->_calculate_pages($query, $total_users)
|
||||
);
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new user for the current blog
|
||||
*
|
||||
* @param array $user User information to add
|
||||
* @return array An array containing the result of the current process
|
||||
*/
|
||||
public function add_user($user) {
|
||||
$this->_admin_include('user.php');
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($user['site_id']) && 0 !== $user['site_id']) $blog_id = $user['site_id'];
|
||||
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to pull users from.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
if (!current_user_can('create_users') && !is_super_admin()) {
|
||||
$result = array('error' => true, 'message' => 'user_create_no_permission', 'data' => array('multisite' => is_multisite()));
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (is_email($user["user_email"]) === false) {
|
||||
$result = array("error" => true, "message" => "email_invalid");
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (email_exists($user["user_email"]) && is_user_member_of_blog(email_exists($user["user_email"]), $blog_id)) {
|
||||
$result = array("error" => true, "message" => "email_exists");
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (username_exists($user["user_login"]) && is_user_member_of_blog(username_exists($user["user_login"]), $blog_id)) {
|
||||
$result = array("error" => true, "message" => "username_exists");
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (!validate_username($user["user_login"])) {
|
||||
$result = array("error" => true, "message" => 'username_invalid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (isset($user['site_id']) && !current_user_can('manage_network_users')) {
|
||||
$result = array("error" => true, "message" => 'user_create_no_permission');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
if (email_exists($user["user_email"]) && !is_user_member_of_blog(email_exists($user["user_email"]), $blog_id)) {
|
||||
$user_id = email_exists($user["user_email"]);
|
||||
} else {
|
||||
$user_id = wp_insert_user($user);
|
||||
}
|
||||
$role = $user['role'];
|
||||
if (is_multisite()) {
|
||||
add_existing_user_to_blog(array('user_id' => $user_id, 'role' => $role));
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
if ($user_id > 0) {
|
||||
$result = array("error" => false, "message" => "user_created_with_user_name", "values" => array($user['user_login']));
|
||||
return $this->_response($result);
|
||||
} else {
|
||||
$result = array("error" => true, "message" => "user_create_failed", "values" => array($user));
|
||||
}
|
||||
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* [delete_user - UCP: users.delete_user]
|
||||
*
|
||||
* This function is used to check to make sure the user_id is valid and that it has has user delete permissions.
|
||||
* If there are no issues, the user is deleted.
|
||||
*
|
||||
* current_user_can: This check the user permissions from UCP
|
||||
* get_userdata: This get the user data on the data from user_id in the $user_id array
|
||||
* wp_delete_user: Deleting users on the User ID (user_id) and, IF Specified, the Assigner ID (assign_user_id).
|
||||
*
|
||||
* @param [type] $params [description] THis is an Array of params sent over from UpdraftCentral
|
||||
* @return [type] Array [description] This will send back an error array along with message if there are any issues with the user_id
|
||||
*/
|
||||
public function delete_user($params) {
|
||||
$this->_admin_include('user.php');
|
||||
$user_id = $params['user_id'];
|
||||
$assign_user_id = $params["assign_user_id"];
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($params['site_id']) && 0 !== $params['site_id']) $blog_id = $params['site_id'];
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
if (!current_user_can('delete_users') && !is_super_admin()) {
|
||||
$result = array('error' => true, 'message' => 'user_delete_no_permission', 'data' => array('multisite' => is_multisite()));
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (get_userdata($user_id) === false) {
|
||||
$result = array("error" => true, "message" => "user_not_found");
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
if (wp_delete_user($user_id, $assign_user_id)) {
|
||||
$result = array("error" => false, "message" => "user_deleted");
|
||||
} else {
|
||||
$result = array("error" => true, "message" => "user_delete_failed");
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits existing user information
|
||||
*
|
||||
* @param array $user User information to save
|
||||
* @return array An array containing the result of the current process
|
||||
*/
|
||||
public function edit_user($user) {
|
||||
$this->_admin_include('user.php');
|
||||
|
||||
// Here, we're getting the current blog id. If blog id
|
||||
// is passed along with the parameters then we override
|
||||
// that current (default) value with the parameter blog id value.
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
if (isset($user['site_id']) && 0 !== $user['site_id']) $blog_id = $user['site_id'];
|
||||
|
||||
// Here, we're switching to the actual blog that we need
|
||||
// to apply our changes.
|
||||
|
||||
$switched = false;
|
||||
if (function_exists('switch_to_blog')) {
|
||||
$switched = switch_to_blog($blog_id);
|
||||
}
|
||||
|
||||
if (!current_user_can('edit_users') && !is_super_admin() && get_current_user_id() !== $user["ID"]) {
|
||||
$result = array('error' => true, 'message' => 'user_edit_no_permission', 'data' => array('multisite' => is_multisite()));
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
if (false === get_userdata($user["ID"])) {
|
||||
$result = array("error" => true, "message" => "user_not_found");
|
||||
return $this->_response($result);
|
||||
}
|
||||
if (get_current_user_id() == $user["ID"]) {
|
||||
unset($user["role"]);
|
||||
}
|
||||
|
||||
/* Validate Username*/
|
||||
if (!validate_username($user["user_login"])) {
|
||||
$result = array("error" => true, "message" => 'username_invalid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
/* Validate Email if not the same*/
|
||||
|
||||
$remote_user = get_userdata($user["ID"]);
|
||||
$old_email = $remote_user->user_email;
|
||||
|
||||
if ($user['user_email'] !== $old_email) {
|
||||
if (is_email($user['user_email']) === false) {
|
||||
$result = array("error" => true, "message" => 'email_invalid');
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
if (email_exists($user['user_email'])) {
|
||||
$result = array("error" => true, "message" => 'email_exists');
|
||||
return $this->_response($result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$user_id = wp_update_user($user);
|
||||
if (is_wp_error($user_id)) {
|
||||
$result = array("error" => true, "message" => "user_edit_failed_with_error", "values" => array($user_id));
|
||||
} else {
|
||||
$result = array("error" => false, "message" => "user_edited_with_user_name", "values" => array($user["user_login"]));
|
||||
}
|
||||
|
||||
// Here, we're restoring to the current (default) blog before we
|
||||
// do the switched.
|
||||
|
||||
if (function_exists('restore_current_blog') && $switched) {
|
||||
restore_current_blog();
|
||||
}
|
||||
|
||||
return $this->_response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves available roles to be used as filter options
|
||||
*
|
||||
* @return array An array containing all available roles
|
||||
*/
|
||||
public function get_roles() {
|
||||
$this->_admin_include('user.php');
|
||||
$roles = array_reverse(get_editable_roles());
|
||||
return $this->_response($roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information to be use as filters
|
||||
*
|
||||
* @return array An array containing the filter fields and their data
|
||||
*/
|
||||
public function get_user_filters() {
|
||||
$this->_admin_include('user.php');
|
||||
|
||||
// Pull sites options if available.
|
||||
$sites = $this->_get_blog_sites();
|
||||
|
||||
$result = array(
|
||||
"sites" => $sites,
|
||||
"roles" => array_reverse(get_editable_roles()),
|
||||
"paging" => $this->_calculate_pages(null, 0),
|
||||
);
|
||||
return $this->_response($result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user