We noticed you have W3 Total Cache already installed. We are not able to fully support this version of W3 Total Cache with A2 Optimized. To get the best options for optimizing your WordPress site, we will help you disable this W3 Total Cache plugin version and install an A2 Hosting supported version of W3 Total Cache in its place.
';
}
if (is_plugin_active('w3-total-cache-fixed/w3-total-cache-fixed.php')) {
$w3tc_fixed_info = get_plugin_data('w3-total-cache-fixed/w3-total-cache-fixed.php');
if (version_compare($w3tc_fixed_info['Version'], '0.9.5.0') >= 0) {
$this->optimization_alert = "
";
$this->optimization_alert .= '
We noticed you have W3 Total Cache already installed. We are not able to fully support this version of W3 Total Cache with A2 Optimized. To get the best options for optimizing your WordPress site, we will help you disable this W3 Total Cache plugin version and install an A2 Hosting supported version of W3 Total Cache in its place.
Please note that you have W3 Total Cache Fixed v0.9.4.x plugin installed. We cannot guarantee our optimizations will be fully supported with this version. To ensure the best compatibility for your WordPress site, please disable the W3 Total Cache Fixed plugin by clicking the button below and install our supported W3 Total Cache plugin, which is based on W3 Total Cache Fixed.
If you would like to keep your currently installed W3 Total Cache Fixed plugin, you may click the button below to dismiss this dialog and enable the optimization options below.
';
}
}
if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
$this->optimization_alert = "
";
$this->optimization_alert .= '
We noticed you are using W3 Total Cache. The version you have installed is outdated and may cause issues with future versions of WordPress. However, A2 Optimized now comes with our own built-in caching engine. To get the best options for optimizing your WordPress site, we will help you disable the W3 Total Cache plugin version and install and configure A2 Optimized caching in place.
Session timed out, please try to configure your optimization again.
';
}
$warning_circle = '';
if ($num_warnings > 0) {
$warning_circle = <<{$num_warnings}
HTML;
}
$settingsGroup = get_class($this) . '-settings-group';
$description = $this->get_plugin_description();
if ($this->is_a2()) {
$feedback = <<
We want to hear from you! Please share your thoughts and feedback in our Suggestion Box!
HTML;
} else {
$feedback = <<
We want to hear from you! Please share your thoughts and feedback in our wordpress.org support forum!
HTML;
}
echo <<
We couldn’t install the new plugin to your site. This is usually caused by permission issues or low disk space. You may need to contact your web host for more information.
You may also download the zip archive of the plugin below and attempt to install it manually.
$item) {
if (md5($date) == $_REQUEST['remove_report']) {
$index_to_remove = $date;
}
}
if ($index_to_remove !== 0) {
unset($existing_health[$index_to_remove]);
update_option('a2opt-sitehealth-results', $existing_health);
}
}
}
/**
* Knowledge Base Searchbox HMTL
*
*/
private function kb_searchbox_html() {
$help_link = "https://wordpress.org/support/plugin/a2-optimized-wp/";
if (class_exists('A2_Optimized_Private_Optimizations')) {
$help_link = "https://my.a2hosting.com/submitticket.php?action=support&type=other";
};
return <<
HTML;
}
/**
* Get a2 token from transients
*/
private function get_a2_token($slug) {
return get_transient('a2_token-' . $slug);
}
/**
* Set a2 token in transients
*/
private function set_a2_token($slug) {
$wp_salt = wp_salt('nonce');
$token = md5(time() . $wp_salt . $slug);
set_transient('a2_token-' . $slug, $token, 180);
return $token;
}
/**
* Get the status of the plugin
*/
public function get_plugin_status() {
$thisclass = $this;
$opts = new A2_Optimized_Optimizations($thisclass);
$this->advanced_optimizations = $opts->get_advanced();
$this->optimizations = $opts->get_optimizations();
$this->plugin_list = get_plugins();
$url_token = false;
if (isset($_GET['a2_token'])) {
$url_token = sanitize_text_field($_GET['a2_token']);
}
if (isset($_GET['disable_optimization']) && $url_token) {
$hash = '';
$optimization = sanitize_text_field($_GET['disable_optimization']);
$a2_token = $this->get_a2_token($optimization);
if ($a2_token && $a2_token == $url_token) {
if (isset($this->optimizations[$optimization])) {
$this->optimizations[$optimization]['disable']($optimization);
}
if (isset($this->advanced_optimizations[$optimization])) {
$this->advanced_optimizations[$optimization]['disable']($optimization);
$hash = '#optimization-advanced-tab';
}
} else {
$hash = '&msg=token';
}
echo <<
window.location = 'admin.php?page=A2_Optimized_Plugin_admin{$hash}';
JAVASCRIPT;
exit();
}
if (isset($_GET['enable_optimization']) && $url_token) {
$hash = '';
$optimization = sanitize_text_field($_GET['enable_optimization']);
$a2_token = $this->get_a2_token($optimization);
if ($a2_token && $a2_token == $url_token) {
if (isset($this->optimizations[$optimization])) {
$this->optimizations[$optimization]['enable']($optimization);
}
if (isset($this->advanced_optimizations[$optimization])) {
$this->advanced_optimizations[$optimization]['enable']($optimization);
$hash = '#optimization-advanced-tab';
}
} else {
$hash = '&msg=token';
}
echo <<
window.location = 'admin.php?page=A2_Optimized_Plugin_admin{$hash}';
JAVASCRIPT;
exit();
}
if (isset($_GET['apply_divi_settings']) && $url_token) {
$this->optimizations['minify']['disable']('minify');
$this->optimizations['css_minify']['disable']('css_minify');
$this->optimizations['js_minify']['disable']('js_minify');
echo <<
window.location = 'admin.php?page=A2_Optimized_Plugin_admin';
JAVASCRIPT;
exit();
}
ini_set('disable_functions', '');
require_once ABSPATH . 'wp-admin/includes/plugin.php';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$plugins_url = plugins_url();
$plugins_url = explode('/', $plugins_url);
array_shift($plugins_url);
array_shift($plugins_url);
array_shift($plugins_url);
$this->plugin_dir = ABSPATH . implode('/', $plugins_url);
$this->plugins_url = plugins_url();
validate_active_plugins();
$this->set_install_status('plugins', $this->plugin_list);
}
/**
* A wrapper function delegating to WP add_option() but it prefixes the input $optionName
* to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
* @return null from delegated call to delete_option()
*/
public function addOption($optionName, $value) {
$prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
return add_option($prefixedOptionName, $value);
}
/**
* Get the prefixed version input $name suitable for storing in WP options
* Idempotent: if $optionName is already prefixed, it is not prefixed again, it is returned without change
* @param $name string option name to prefix. Defined in settings.php and set as keys of $this->optionMetaData
* @return string
*/
public function prefix($name) {
$optionNamePrefix = $this->getOptionNamePrefix();
if (strpos($name, $optionNamePrefix) === 0) { // 0 but not false
return $name; // already prefixed
}
return $optionNamePrefix . $name;
}
public function getOptionNamePrefix() {
return get_class($this) . '_';
}
/**
* Deactivate the plugin
* @param string $file The name of the plugin to deactivate
*
*/
public function deactivate_plugin($file) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
if (is_plugin_active($file)) {
deactivate_plugins($file);
$this->clear_w3_total_cache();
}
}
/**
* Uninstall the plugin
* @param string $file The name of the plugin to uninstall
* @param boolean $delete Delete plugin files after uninstall
*
*/
public function uninstall_plugin($file, $delete = true) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$this->deactivate_plugin($file);
uninstall_plugin($file);
if ($delete) {
delete_plugins([$file]);
}
unset($this->plugin_list[$file]);
$this->clear_w3_total_cache();
}
/**
* Set the install status for the plugin
* @param string $name The name of the plugin
* @param string $value The status of the plugin
*
*/
public function set_install_status($name, $value) {
if (!isset($this->install_status)) {
$this->install_status = new StdClass;
}
$this->install_status->{$name} = $value;
}
/**
* Define your options meta data here as an array, where each element in the array
* @return array of key=>display-name and/or key=>array(display-name, choice1, choice2, ...)
* key: an option name for the key (this name will be given a prefix when stored in
* the database to ensure it does not conflict with other plugin options)
* value: can be one of two things:
* (1) string display name for displaying the name of the option to the user on a web page
* (2) array where the first element is a display name (as above) and the rest of
* the elements are choices of values that the user can select
* e.g.
* array(
* 'item' => 'Item:', // key => display-name
* 'rating' => array( // key => array ( display-name, choice1, choice2, ...)
* 'CanDoOperationX' => array('Can do Operation X', 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber'),
* 'Rating:', 'Excellent', 'Good', 'Fair', 'Poor')
*/
public function getOptionMetaData() {
return [];
}
private function curl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
/*public function get_litespeed(){
return get_option('a2_optimized_litespeed');
}*/
/*public function set_litespeed($litespeed = true){
update_option('a2_optimized_litespeed',$litespeed);
}*/
public function get_optimization_status(&$item, $server_info) {
if ($item != null) {
if ($this->is_a2_managed() && isset($item['hide_managed']) && $item['hide_managed'] === true) {
return;
}
$settings_slug = $this->getSettingsSlug();
if (isset($item['is_configured'])) {
$item['is_configured']($item);
}
$active_color = 'danger';
$active_text = 'Not Activated';
$glyph = 'exclamation-sign';
$links = [];
$active_class = '';
if (
isset($item['plugin']) && $item['plugin'] == 'W3 Total Cache'
&& (
$this->is_plugin_installed('a2-w3-total-cache/a2-w3-total-cache.php') === false
|| is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php') === false
)
) {
$active_class = 'inactive';
return;
}
if ($item['configured']) {
$active_color = 'success';
$active_text = 'Configured';
$glyph = 'ok';
if (isset($item['disable'])) {
if (isset($item['remove_link']) && $item['remove_link'] == true && ($server_info->cf || $server_info->gzip || $server_info->br)) {
// skip adding "disable" link if 'remove_link' key is set and site is behind cloudflare
// used for Gzip options
} else {
$a2_token = $this->set_a2_token($item['slug']);
$links[] = ["?page=$settings_slug&disable_optimization={$item['slug']}&a2_token={$a2_token}", 'Disable', '_self'];
}
}
if (isset($item['settings'])) {
$links[] = ["{$item['settings']}", 'Configure', '_self'];
}
if (isset($item['configured_links'])) {
foreach ($item['configured_links'] as $name => $link) {
if (gettype($link) == 'array') {
$links[] = [$link[0], $name, $link[1]];
} else {
$links[] = [$link, $name, '_self'];
}
}
}
} elseif (isset($item['partially_configured']) && $item['partially_configured']) {
$active_color = 'warning';
$active_text = 'Partially Configured.';
if (isset($item['partially_configured_message'])) {
$active_text .= " {$item['partially_configured_message']}";
}
$glyph = 'warning-sign';
if (isset($item['disable'])) {
$a2_token = $this->set_a2_token($item['slug']);
$links[] = ["?page=$settings_slug&disable_optimization={$item['slug']}&a2_token={$a2_token}", 'Disable', '_self'];
}
if (isset($item['settings'])) {
$links[] = ["{$item['settings']}", 'Configure', '_self'];
}
if (isset($item['partially_configured_links'])) {
foreach ($item['partially_configured_links'] as $name => $link) {
if (gettype($link) == 'array') {
$links[] = [$link[0], $name, $link[1]];
} else {
$links[] = [$link, $name, '_self'];
}
}
}
} elseif (isset($item['optional']) && $item['optional']) {
$active_color = 'warning';
$active_text = 'Optional';
$glyph = 'warning-sign';
if (isset($item['enable']) && $active_class == '') {
$action_text = 'Enable';
if (isset($item['update'])) {
$action_text = 'Update Now';
}
$a2_token = $this->set_a2_token($item['slug']);
$links[] = ["?page=$settings_slug&enable_optimization={$item['slug']}&a2_token={$a2_token}", $action_text, '_self'];
}
if (isset($item['not_configured_links'])) {
foreach ($item['not_configured_links'] as $name => $link) {
if (gettype($link) == 'array') {
$links[] = [$link[0], $name, $link[1]];
} else {
$links[] = [$link, $name, '_self'];
}
}
}
} else {
if (isset($item['enable']) && $active_class == '') {
$a2_token = $this->set_a2_token($item['slug']);
$links[] = ["?page=$settings_slug&enable_optimization={$item['slug']}&a2_token={$a2_token}", 'Enable', '_self'];
}
if (isset($item['not_configured_links'])) {
foreach ($item['not_configured_links'] as $name => $link) {
if (gettype($link) == 'array') {
$links[] = [$link[0], $name, $link[1]];
} else {
$links[] = [$link, $name, '_self'];
}
}
}
}
if (isset($item['kb'])) {
$links[] = [$item['kb'], 'Learn More', '_blank'];
}
$link_html = '';
foreach ($links as $i => $link) {
if (isset($link[0]) && isset($link[1]) && isset($link[2])) {
$link_html .= <<{$link[1]} |
HTML;
}
}
$premium = '';
if (isset($item['premium'])) {
$premium = '
HTML;
}
/*
public function plugin_list(){
//Name,PluginURI,Version,Description,Author,AuthorURI,TextDomain,DomainPath,Network,Title,AuthorName
$string = "";
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
$plugins = $this->get_plugins();
foreach($plugins as $filename=>$plugin){
$name = $plugin['Name'];
$title = $plugin['Title'];
$checked = "";
if(is_plugin_active($filename)){
$checked = "checked='checked'";
}
ob_start();
$dump = ob_get_contents();
ob_end_clean();
$string .=<<
$titledelete
{$dump}
HTML;
}
return $string;
}*/
/**
* Set the install status for the plugin
* @param string $plugin The name of the plugin
*
* @return markup HTML the formatted HTML to display plugin status on web page
*
*/
private function plugin_not_active_warning($plugin) {
$manage = 'plugins.php?plugin_status=inactive';
return <<
Inactive Plugin: {$plugin['Name']}
Deactivated plugins should be deleted. Deactivating a plugin does not remove the plugin and its files from your website. Plugins with security flaws may still affect your site even when not active.
HTML;
}
/**
* Get the advanced optimizations for A2Optimized
*
* @return array @advanved_optimizations An array of optimization options
*/
public function get_advanced_optimizations() {
return $this->advanced_optimizations;
}
/**
* Set the lockdown status for the plugin
* @param boolean $lockdown Lockdown enabled or disabled
*
*/
public function set_lockdown($lockdown = true) {
if ($lockdown == false) {
delete_option('a2_optimized_lockdown');
} else {
update_option('a2_optimized_lockdown', $lockdown);
}
}
public function set_nomods($lockdown = true) {
if ($lockdown == false) {
delete_option('a2_optimized_nomods');
} else {
update_option('a2_optimized_nomods', $lockdown);
}
}
/**
* Set the install status for the plugin
* @param boolean $deny Deny direct access option
*
*/
public function set_deny_direct($deny = true) {
if ($deny == false) {
delete_option('a2_optimized_deny_direct');
} else {
update_option('a2_optimized_deny_direct', $deny);
}
}
/**
* Write the config options
*
*/
public function write_wp_config() {
$lockdown = $this->get_lockdown();
$nomods = $this->get_nomods();
$obj_server = $this->get_memcached_server();
$backup_filename = 'wp-config.bak-a2.php';
$error_message = '
Unable to write to ' . ABSPATH . 'wp-config.php. Please check file permissions.
';
if (!file_exists(ABSPATH . 'wp-config.php')) {
echo $error_message;
exit;
}
touch(ABSPATH . 'wp-config.php');
copy(ABSPATH . 'wp-config.php', ABSPATH . $backup_filename);
$config_hash = sha1(file_get_contents(ABSPATH . 'wp-config.php'));
$backup_config_hash = sha1(file_get_contents(ABSPATH . $backup_filename));
if ($config_hash != $backup_config_hash || filesize(ABSPATH . $backup_filename) == 0) {
echo $error_message;
exit;
}
$a2_config = << array('{$obj_server}')));
PHP;
}
$a2_config .= <<get_deny_direct()) {
//Append the new rules to .htaccess
//get the path to the WordPress install - nvm
//$rewrite_base = "/".trim(explode('/',str_replace(array('https://','http://'),'',site_url()),2)[1],"/")."/";
$a2hardening = <<
Order deny,allow
Deny from all
RewriteBase {$home_path}
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
RewriteRule ^wp-config\.php - [F,L]
RewriteRule ^php\.ini - [F,L]
RewriteRule \.htaccess - [F,L]
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .wp-comments-post.php*
RewriteCond %{HTTP_REFERER} !.*{$_SERVER['HTTP_HOST']}.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) - [F,L]
# END WordPress Hardening
APACHE;
}
$litespeed = '';
$htaccess = file_get_contents(ABSPATH . '.htaccess');
$pattern = "/[\r\n]*# BEGIN WordPress Hardening.*# END WordPress Hardening[\r\n]*/msiU";
$htaccess = preg_replace($pattern, '', $htaccess);
$htaccess = <<optionMetaData
* @return bool from delegated call to delete_option()
*/
public function deleteOption($optionName) {
$prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
return delete_option($prefixedOptionName);
}
/**
* A wrapper function delegating to WP add_option() but it prefixes the input $optionName
* to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $value mixed the new value
* @return null from delegated call to delete_option()
*/
public function updateOption($optionName, $value) {
$prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
return update_option($prefixedOptionName, $value);
}
/**
* Checks if a particular user has a role.
* Returns true if a match was found.
*
* @param string $role Role name.
* @param int $user_id (Optional) The ID of a user. Defaults to the current user.
* @return bool
*/
public function checkUserRole($role, $user_id = null) {
if (is_numeric($user_id)) {
$user = get_userdata($user_id);
} else {
$user = wp_get_current_user();
}
return empty($user) ? false : in_array($role, (array)$user->roles);
}
/**
* A wrapper function delegating to WP get_option() but it prefixes the input $optionName
* to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
* @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
* @param $default string default value to return if the option is not set
* @return string the value from delegated call to get_option(), or optional default value
* if option is not set.
*/
public function getOption($optionName, $default = null) {
$prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
$retVal = get_option($prefixedOptionName);
if (!$retVal && $default) {
$retVal = $default;
}
return $retVal;
}
/**
* @param $roleName string a standard WP role name like 'Administrator'
* @return bool
*/
public function isUserRoleEqualOrBetterThan($roleName) {
if ('Anyone' == $roleName) {
return true;
}
$capability = $this->roleToCapability($roleName);
return $this->checkUserCapability($capability);
}
/**
* Given a WP role name, return a WP capability which only that role and roles above it have
* http://codex.wordpress.org/Roles_and_Capabilities
* @param $roleName
* @return string a WP capability or '' if unknown input role
*/
protected function roleToCapability($roleName) {
switch ($roleName) {
case 'Super Admin':
return 'manage_options';
case 'Administrator':
return 'manage_options';
case 'Editor':
return 'publish_pages';
case 'Author':
return 'publish_posts';
case 'Contributor':
return 'edit_posts';
case 'Subscriber':
return 'read';
case 'Anyone':
return 'read';
}
return '';
}
/**
* Checks if a particular user has a given capability without calling current_user_can.
* Returns true if a match was found.
*
* @param string $capability Capability name.
* @param int $user_id (Optional) The ID of a user. Defaults to the current user.
* @return bool
*/
public function checkUserCapability($capability, $user_id = null) {
if (!is_numeric($user_id)) {
$user = wp_get_current_user();
} else {
$user = get_userdata($user_id);
}
if (is_object($user)) {
$capabilities = (array)$user->allcaps;
if (isset($capabilities[$capability])) {
return $capabilities[$capability];
}
}
return false;
}
/**
* Check Check for the correct a2_optimized directory
* @return boolean true|false
*/
protected function is_a2() {
if (is_dir('/opt/a2-optimized')) {
return true;
}
return false;
}
/**
* Check to see if this is a ManagedWP install
*
* return bool
*/
protected function is_a2_managed() {
return file_exists('/opt/a2-optimized/wordpress/a2managed');
}
/**
* Check for installed plugin
* @param string $slug The plugin that we check for installation
* @return boolean true|false
*/
private function is_plugin_installed($slug) {
$plugins = get_plugins();
if (array_key_exists($slug, $plugins)) {
return true;
}
return false;
}
/**
* Check for a valid and active w3tc plugin
* @return boolean true|false
*/
private function is_valid_w3tc_installed() {
/* W3 Total Cache Offical is not valid */
if (is_plugin_active('w3-total-cache/w3-total-cache.php')) {
return false;
}
/* W3 Total Cache Fixed < 0.9.5.x is ok */
if (is_plugin_active('w3-total-cache-fixed/w3-total-cache-fixed.php')) {
$w3tc_fixed_info = get_plugin_data('w3-total-cache-fixed/w3-total-cache-fixed.php');
if (version_compare($w3tc_fixed_info['Version'], '0.9.5.0') >= 0) {
return false;
} else {
return true;
}
}
/* A2 Fixed W3TC is ok */
if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
return true;
}
return false;
}
public function getVersion() {
return $this->getPluginHeaderValue('Version');
}
public function getPluginHeaderValue($key) {
// Read the string from the comment header of the main plugin file
$data = file_get_contents($this->getPluginDir() . DIRECTORY_SEPARATOR . $this->getMainPluginFileName());
$match = [];
preg_match('/' . $key . ':\s*(\S+)/', $data, $match);
if (count($match) >= 1) {
return $match[1];
}
return null;
}
protected function getPluginDir() {
return dirname(__FILE__);
}
/**
* Generates a random string of lower case letters, used for Rename WP Login URL
*
* @param int $length The length of the random string
* @return string $output The random string
*/
public function getRandomString($length = 4) {
$output = '';
$valid_chars = 'abcdefghijklmnopqrstuvwxyz';
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++) {
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick - 1];
// add the randomly-chosen char onto the end of our string so far
$output .= $random_char;
}
return $output;
}
/**
* Get the description for the plugin
* @return string $description The description of the plugin
*/
public function get_plugin_description() {
$description = <<