Edit file File name : class.A2OptWordPress.php Content :<?php class A2OptWordPress extends A2OptBase { public $memcached_instance; private $mysqli; private $dbpass; private $dbhost; private $dbuser; private $dbname; private $config_file; private $memcached_socket; private $w3tc_keys; private $w3tc_master; private $pdo; private $htaccess; private $sqlfile; private $config; public $title; public $domain; public $path; public $type; public $connected; public $siteurl; public $homeurl; public $loginurl; public $adminurl; public $can_login; public $exit_on_error; public $ssl; public $iscagefs; public $a2_optimized; public $a2_optimized_installed; public $a2_cache_available; public $is_litespeed_enabled; public $new_w3tc_keys; public $notes; public function __construct($app) { $this->exit_on_error = false; //$this->pdo = new PDO(""); $this->app = $app; $this->path = $this->app->path; $this->domain = $this->app->domain; $this->type = 'WordPress'; $this->ssl_admin = false; $this->ssl_content = false; $this->ssl_login = false; $this->ssl = false; $this->iscagefs = $this->is_cagefs(); chdir($this->path); $this->get_home(); if (!file_exists("{$this->path}/wp-config.php")) { $this->log_action('No wp-config.php for ' . $this->path); $this->type = null; return; } if (!file_exists("{$this->path}/wp-settings.php")) { $this->log_action('No wp-settings.php for ' . $this->path); $this->type = null; return; } $this->notes = []; $this->memcached_socket = null; $this->dbname = ''; $this->dbpass = ''; $this->dbhost = ''; $this->dbuser = ''; $this->dbprefix = 'wp_'; $this->contentdir = "{$this->path}/wp-content"; $this->config_file = "{$this->path}/wp-config.php"; $this->config_file_contents = file_get_contents($this->config_file); $this->settings_file = "{$this->path}/wp-settings.php"; $this->settings_file_contents = file_get_contents($this->settings_file); $this->config = $this->get_defines(); $this->contentdir = $this->get_config('WP_CONTENT_DIR'); if (empty($this->contentdir)) { $this->contentdir = "{$this->path}/wp-content"; } $this->dbpass = $this->get_config('DB_PASSWORD'); $this->dbuser = $this->get_config('DB_USER'); $this->dbhost = $this->get_config('DB_HOST'); $this->dbname = $this->get_config('DB_NAME'); if (strpos($this->dbhost, ':') !== false) { // DB host string has host:port for some reason... // We're going to grab the first part, which should be the host name $parts = explode(':', $this->dbhost); $this->dbhost = $parts[0]; $this->dbport = $parts[1]; } if (preg_match('/\$table_prefix\s*=\s*[\'"](.+)[\'"]/', $this->config_file_contents, $matched)) { $this->dbprefix = array_pop($matched); } //$this->error(json_encode($this->config)); if (!$this->db_connect()) { $this->log_action('Unable to connect to db ' . $this->path); $this->domain = ''; $this->connected = false; $this->mysqli = null; $this->type = null; return false; } if ($this->a2_optimized_installed = $this->is_a2_optimized_installed()) { if ($this->a2_optimized = $this->is_a2_optimized_activated()) { $this->a2_cache_available = $this->can_use_a2_optimized_cache(); } } $this->is_litespeed_enabled = $this->is_litespeed_enabled(); $this->connected = true; $this->title = $this->check_app_title($this->get_option('blogname'), $app); $this->w3tc_keys = $this->get_w3tc_keys($this->contentdir); $this->w3tc_master = $this->get_w3tc_master(); $this->new_w3tc_keys = []; $this->ssl = $this->is_ssl($this->url2domain($this->homeurl)); if ( !( $this->siteurl = $this->get_config('WP_SITEURL') ) ) { $this->siteurl = $this->get_option('site_url'); } if ( !( $this->homeurl = $this->get_config('WP_HOME') ) ) { $this->homeurl = $this->get_option('home'); } if ( !( $this->ssl_admin = $this->get_config('FORCE_SSL_ADMIN') ) ) { $this->ssl_admin = false; } $this->ssl_login = $this->ssl_admin; $this->can_login = true; $this->loginurl = $this->get_login_url(); $status = $this->check_wp_cli(); if (!empty($status)) { $this->notes[] = $status; $this->log_action('Notes for ' . $this->path . ':::' . json_encode($this->notes)); } if (!$this->check_bad_strings()) { $this->notes[] = 'Possible malware found on this install. Please check wp-config.php or contact support.'; $this->log_action('Possible malware found in ' . $this->path); } $this->exit_on_error = true; } /** * return a named value from the config array * @param $key * @return string|bool */ private function get_config($key) { if (!isset($this->config[$key])) { return false; } return $this->config[$key]; } /** * checks wp-config contents for bad strings. returns false if found * @return bool */ private function check_bad_strings() { if (!(isset($this->config_file_contents) && isset($this->settings_file_contents))) { return false; } // List of known stuff that should not be in wp-config. We expect to add to this list in the future. $bad_strings = [ '@include', ]; foreach ($bad_strings as $bad_string) { $found = stripos($this->config_file_contents, $bad_string); if ($found !== false) { // bad string found return false; } } return true; } /** * return an array of all the definied values in wp-config and wp-settings * * @return array * */ public function get_defines() { if (!(isset($this->config_file_contents) && isset($this->settings_file_contents))) { return null; } $config = []; preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*[\'"](?<value>.*)[\'"]\s*\)/', $this->config_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = $matched['value'][$i]; } preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*[\'"](?<value>.*)[\'"]\s*\)/', $this->settings_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = $matched['value'][$i]; } preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*true\s*\)/', $this->config_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = true; } preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*true\s*\)/', $this->settings_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = true; } preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*false\s*\)/', $this->config_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = false; } preg_match_all('/define\(\s*[\'"](?<name>[^\'"]*)[\'"]\s*,\s*false\s*\)/', $this->settings_file_contents, $matched); foreach ($matched['name'] as $i => $value) { $config[$value] = false; } return $config; } public function is_a2_optimized_activated() { $res = $this->wp_cli('plugin status | grep a2-optimized'); if (strpos($res, 'A a2-optimized') === false && strpos($res, 'N a2-optimized') === false) { return false; } return true; } public function is_a2_optimized_installed() { $res = $this->wp_cli('plugin status | grep a2-optimized'); if (strpos($res, 'a2-optimized-wp') === false) { return false; } return true; } public function can_use_a2_optimized_cache() { $res = $this->wp_cli('plugin get a2-optimized-wp | grep version'); if (strpos($res, 'ion2.0.') === false) { return true; } return false; } public function is_using_a2_optimized_cache() { $caching_enabled = $this->get_option('a2_cache_enabled'); $cache_dropin_exists = file_exists($this->app->path . '/wp-content/advanced-cache.php'); if ($this->is_litespeed_enabled) { // Litespeed caching counts as page caching return true; } if ( $this->a2_optimized && $this->a2_cache_available && $caching_enabled == 1 && $cache_dropin_exists == 1 ) { return true; } return false; } public function is_w3tc_enabled() { $res = $this->wp_cli('plugin status | grep a2-w3-total-cache'); if (strpos($res, 'A a2-w3-total-cache') === false && strpos($res, 'N a2-w3-total-cache') === false) { return false; } else { return true; } } private function set_login_token() { $token = uniqid('a2_', true); $this->set_option('a2_auth_token', $token); $this->set_option('a2_auth_token_expires', time() + 35); copy(__DIR__ . '/../a2_wp_authenticate.php', "{$this->path}/a2_wp_authenticate.php"); return "{$token}"; } public function get_login_token() { return $this->set_login_token(); } public function flush_cache() { chdir($this->path); if ($this->is_w3tc_enabled()) { $res = $this->wp_cli('cache flush'); $res = $this->wp_cli('w3-total-cache flush all', true); $res = $this->wp_cli('w3-total-cache flush db', true); $res = $this->wp_cli('w3-total-cache flush object', true); $res = $this->wp_cli('w3-total-cache flush minify', true); $res = $this->wp_cli('w3-total-cache flush fragment', true); } if ($this->is_using_a2_optimized_cache()) { // Using A2 Opt cache $res = $this->wp_cli('cache flush'); $res = $this->wp_cli('a2-optimized clear', true); } } public function filter_wp_cli($output) { $lines = explode("\n", $output); $i = 0; foreach ($lines as $line) { if (substr($line, 0, 11) == 'Deprecated:' || substr($line, 0, 8) == 'Warning:') { unset($lines[$i]); } $i++; } $output = implode("\n", $lines); return $output; } public function wp_cli($command, $w3tc = false, $filter_output = false) { chdir($this->path); //$command = escapeshellcmd($command); if (true === $w3tc) { $command = "wp --path={$this->path} {$command}"; } else { $command = "wp --skip-plugins=a2-w3-total-cache --path={$this->path} {$command}"; } //$this->error("running wp-cli -- {$command}"); $answer = $this->su_exec($command); //$this->log_error("response -- {$answer}\n"); //Only allow ASCII charcaters to come back from WP-CLI output $answer = preg_replace('/[^\x20-\x7E]/', '', $answer); if ($filter_output == true) { $answer = $this->filter_wp_cli($answer); } return $answer; } protected function check_wp_cli() { $status = ''; $result = $this->get_home_url(); //$this->error("$result == {$this->homeurl}"); if ($result != $this->homeurl || empty($result) ) { $status = 'The WP CLI is not connecting properly. Your configuration may be incompatible with the advanced features of A2 Optimized.'; } else { $status = ''; } return $status; } public function get_site_url() { chdir($this->path); $https = $this->ssl ? 'on' : 'off'; $output = $this->wp_cli("eval '\$_SERVER[\"HTTPS\"] = \"{$https}\"; echo get_site_url();'"); $lines = explode("\n", $output); foreach ($lines as $url) { if ($this->is_valid_url($url)) { return $url; } } return false; } public function get_ssl_admin() { chdir($this->path); return $this->wp_cli("eval 'echo force_ssl_admin();'", false, true); } public function get_ssl_content() { chdir($this->path); return $this->wp_cli("eval 'echo force_ssl_content();'", false, true); } public function get_ssl_login() { chdir($this->path); return $this->wp_cli("eval 'echo force_ssl_login();'", false, true); } public function get_home_url() { chdir($this->path); $https = $this->ssl ? 'on' : 'off'; $output = $this->wp_cli('option get siteurl'); $lines = explode("\n", $output); foreach ($lines as $url) { if ($this->is_valid_url($url)) { if ($https == 'on') { $url = str_replace('http://', 'https://', $url); } return $url; } } return false; } public function get_login_url() { $home_url = $this->get_home_url(); if ($home_url) { return $home_url . '/wp-login.php'; } return false; } public function get_admin_url() { chdir($this->path); $https = $this->ssl ? 'on' : 'off'; $output = $this->wp_cli("eval 'echo get_admin_url();'"); $lines = explode("\n", $output); foreach ($lines as $url) { if ($this->is_valid_url($url)) { if ($https == 'on') { $url = str_replace('http://', 'https://', $url); } return $url; } } return false; } /** * Checks that a string is a valid URL, or at least beings with http */ private function is_valid_url($url) { if (substr($url, 0, 4) == 'http' ) { // Make sure we get a valid URL back before passing it along return true; } return false; } /** * get a database connection from the info in the wp-config.php file */ public function db_connect() { if ($this->dbhost != '' && $this->dbpass != '' && $this->dbuser != '' && $this->dbname != '') { if (!($this->mysqli = mysqli_connect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname))) { $this->mysqli = null; $this->type = null; return false; } try { $this->pdo = new A2OptPDO($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname); } catch (PDOException $e) { $this->mysqli = null; $this->type = null; return false; } return true; } $this->mysqli = null; $this->type = null; return false; } /* * returns option_value for supplied option_name from this WordPress site * * @param $option_name * @return string|bool */ public function get_option($option_name) { if (!is_null($this->mysqli)) { $value = null; $tablename = $this->get_table('options'); if (empty($tablename)) { $this->log_error('Unable to load WP options table on db ' . $this->dbname . ' for ' . $this->path); return false; } $stmt = $this->mysqli->prepare('select option_value from ' . $tablename . ' where option_name=?;'); $stmt->bind_param('s', $option_name); $stmt->execute(); $stmt->store_result(); $stmt->bind_result($value); if ($stmt->num_rows >= 1) { $stmt->fetch(); return $value; } } return false; } private function set_option($option_name, $value) { if (!is_null($this->mysqli)) { chdir($this->path); $res = $this->wp_cli("option update {$option_name} $value"); $this->flush_cache(); return true; } return false; } public function can_connect() { return (!is_null($this->mysqli)); } public function get_optimizations() { if (!$this->is_w3tc_enabled() && !$this->is_using_a2_optimized_cache()) { $caching_warning = 'This will install and optimize your site with the A2 Optimized for WordPress plugin. If you already have a caching plugin installed and configured, this may break your site. Would you like to proceed?'; } else { $caching_warning = ''; } if ($this->is_w3tc_enabled() || ($this->is_a2_optimized_installed() && !$this->a2_cache_available)) { // W3 Total Cache is active OR A2 Optimized is installed but is an older version $optimizations = [ 'Page Cache' => [ 'optimized' => $this->get_w3tc_config('pgcache.enabled'), 'description' => 'Creates a full page cache of html pages generated by php code', 'optimized_value' => [ 'pgcache.enabled' => true, 'pgcache.debug' => true, ], 'deoptimized_value' => [ 'pgcache.enabled' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'Database Cache' => [ 'optimized' => $this->get_w3tc_config('dbcache.enabled'), 'description' => 'Creates a cache of database query results to speed up page load times', 'optimized_value' => [ 'dbcache.enabled' => true, 'dbcache.debug' => true, ], 'deoptimized_value' => [ 'dbcache.enabled' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'Object Cache' => [ 'optimized' => $this->get_w3tc_config('objectcache.enabled'), 'description' => 'Creates a cache of WordPress objects such as widgets, sidebars and forms', 'optimized_value' => [ 'objectcache.enabled' => true, 'objectcache.debug' => true, ], 'deoptimized_value' => [ 'objectcache.enabled' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'HTML Minification' => [ 'optimized' => ($this->get_w3tc_config('minify.enabled') && ($this->get_w3tc_config('minify.auto') || $this->get_w3tc_config('minify.html.enable'))), 'description' => 'Reduces the download size of html pages through minification.', 'optimized_value' => [ 'minify.enabled' => true, 'minify.auto' => false, 'minify.html.enable' => true, 'minify.debug' => true, ], 'deoptimized_value' => [ 'minify.html.enable' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'CSS Minification' => [ 'optimized' => ($this->get_w3tc_config('minify.enabled') && ($this->get_w3tc_config('minify.auto') || $this->get_w3tc_config('minify.css.enable'))), 'description' => 'Caches CSS files and reduces the download size through minification.', 'optimized_value' => [ 'minify.enabled' => true, 'minify.auto' => false, 'minify.css.enable' => true, 'minify.debug' => true, ], 'deoptimized_value' => [ 'minify.css.enable' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'JavaScript Minification' => [ 'optimized' => ($this->get_w3tc_config('minify.enabled') && ($this->get_w3tc_config('minify.auto') || $this->get_w3tc_config('minify.js.enable'))), 'description' => 'Caches JS files and reduces the download size through minification.', 'optimized_value' => [ 'minify.enabled' => true, 'minify.auto' => false, 'minify.js.enable' => true, 'minify.debug' => true, ], 'deoptimized_value' => [ 'minify.js.enable' => false ], 'type' => 'w3tc', 'warning' => $caching_warning, ], 'A2 Optimized WordPress' => [ 'optimized' => $this->a2_optimized, 'description' => 'Enable more great optimizations for WordPress by installing the A2 Optimized for WordPress plugin.', 'type' => 'plugin', 'warning' => 'This will install the A2 Optimized Plugin for WordPress. Make sure your site is backed up before continuing.', 'plugin' => 'a2-optimized-wp' ], 'Memcached' => [ 'optimized' => $this->is_memcached_enabled(), 'description' => 'Caching of database query results in memory', 'controller' => 'Memcached', 'advanced' => true ], 'TurboCache' => [ 'optimized' => $this->is_litespeed_enabled, 'description' => 'Static file caching by the web Server', 'controller' => 'TurboCache', 'advanced' => true ] ]; } else { // W3 Total Cache is not active, or A2 Optimized is a version that supports built-in caching or is not installed (and we'll install it) $optimizations = [ 'A2 Optimized WordPress' => [ 'optimized' => $this->a2_optimized, 'description' => 'Enable more great optimizations for WordPress by installing the A2 Optimized for WordPress plugin.', 'type' => 'plugin', 'warning' => 'This will install the A2 Optimized Plugin for WordPress. Make sure your site is backed up before continuing.', 'plugin' => 'a2-optimized-wp' ], 'Page Cache' => [ 'optimized' => $this->is_using_a2_optimized_cache(), 'description' => 'Creates a full page cache of html pages generated by php code', 'optimized_value' => [ 'page_cache' => 'enable', ], 'deoptimized_value' => [ 'page_cache' => 'disable' ], 'type' => 'a2-optimized', 'warning' => $caching_warning, ], 'Object Caching with Memcached' => [ 'optimized' => $this->is_memcached_enabled(), 'description' => 'Creates a cache of WordPress objects such as widgets, sidebars and forms', 'optimized_value' => [ 'objectcache.enabled' => true, ], 'deoptimized_value' => [ 'objectcache.enabled' => false ], 'type' => 'memcached', 'warning' => $caching_warning, ], 'Object Caching with Redis' => [ 'optimized' => $this->is_redis_enabled(), 'description' => 'Creates a cache of WordPress objects such as widgets, sidebars and forms', 'optimized_value' => [ 'objectcache.enabled' => true, ], 'deoptimized_value' => [ 'objectcache.enabled' => false ], 'type' => 'redis', 'warning' => $caching_warning, ], 'GZIP Cached Pages' => [ 'optimized' => (($this->get_a2_cache_setting('compress_cache') && $this->is_using_a2_optimized_cache()) || $this->is_litespeed_enabled), 'description' => 'Makes your site significantly faster by compressing all text files to make them smaller', 'optimized_value' => [ 'gzip' => 'enable', ], 'deoptimized_value' => [ 'gzip' => 'disable' ], 'type' => 'a2-optimized', 'warning' => $caching_warning, ], 'HTML Minification' => [ 'optimized' => ($this->get_a2_cache_setting('minify_html') && $this->is_using_a2_optimized_cache()), 'description' => 'Reduces the download size of html pages through minification.', 'optimized_value' => [ 'html_min' => 'enable', ], 'deoptimized_value' => [ 'html_min' => 'disable' ], 'type' => 'a2-optimized', 'warning' => $caching_warning, ], 'CSS & Javascript Minification' => [ 'optimized' => ($this->get_a2_cache_setting('minify_inline_css_js') && $this->is_using_a2_optimized_cache()), 'description' => 'Inline CSS and Javascript is minified for cached pages. This may cause issues with some page builder plugins.', 'optimized_value' => [ 'cssjs_min' => 'enable' ], 'deoptimized_value' => [ 'cssjs_min' => 'disable' ], 'type' => 'a2-optimized', 'warning' => $caching_warning, ], 'TurboCache' => [ 'optimized' => $this->is_litespeed_enabled, 'description' => 'Static file caching by the web Server', 'controller' => 'TurboCache', 'advanced' => true ] ]; } if (!$this->a2_optimized && !$this->is_litespeed_enabled) { $optimizations = [ 'A2 Optimized WordPress' => [ 'optimized' => $this->a2_optimized, 'description' => 'Enable more great optimizations for WordPress by installing the A2 Optimized for WordPress plugin.', 'type' => 'plugin', 'plugin' => 'a2-optimized-wp', 'warning' => 'This will install the A2 Optimized Plugin for WordPress. Make sure your site is backed up before continuing.' ], 'Install the A2 Optimized for WordPress Plugin to get more great options for optimizing your site' => [ 'optimized' => $this->app->swiftcache->turbocache->enabled ], 'Memcached' => [ 'optimized' => $this->is_memcached_enabled(), 'description' => 'Caching of database query results in memory', 'controller' => 'Memcached', 'advanced' => true ], 'TurboCache' => [ 'optimized' => $this->is_litespeed_enabled, 'description' => 'Static file caching by the web Server', 'controller' => 'TurboCache', 'advanced' => true ] ]; } if ($this->is_litespeed_enabled) { unset($optimizations['HTML Minification']); unset($optimizations['CSS & Javascript Minification']); } if (!$this->is_redis_available()) { unset($optimizations['Object Caching with Redis']); } return $optimizations; } public function set_optimization($name, $optimize, $refresh_w3tc = true) { $optimizations = $this->get_optimizations(); $updated_w3tc = false; if (array_key_exists($name, $optimizations)) { if (isset($optimizations[$name]['type'])) { switch ($optimizations[$name]['type']) { case 'w3tc': if ($optimize) { if (!$this->is_w3tc_enabled()) { $this->enable_w3tc(); } //$this->set_w3tc_key($optimizations[$name]["optimized_value"],$refresh_w3tc); $this->save_w3tc($optimizations[$name]['optimized_value']); } else { //$this->set_w3tc_key($optimizations[$name]["deoptimized_value"],$refresh_w3tc); $this->save_w3tc($optimizations[$name]['deoptimized_value']); } break; case 'plugin': if ($optimizations[$name]['plugin'] == 'a2-optimized-wp') { if ($optimize) { if (!$this->is_a2_optimized_installed()) { $this->wp_cli('plugin install a2-optimized-wp --activate'); $this->a2_cache_available = $this->can_use_a2_optimized_cache(); } elseif (!$this->a2_optimized) { $this->wp_cli('plugin install a2-optimized-wp'); $this->wp_cli('plugin activate a2-optimized-wp'); $this->a2_cache_available = $this->can_use_a2_optimized_cache(); } $this->a2_optimized = $this->is_a2_optimized_activated(); } else { $this->wp_cli('plugin deactivate a2-optimized-wp'); $this->a2_optimized = false; $this->a2_cache_available = false; } } break; case 'a2-optimized': if ($optimize) { if (!$this->is_using_a2_optimized_cache() && $this->a2_cache_available) { $this->enable_a2_optimized_cache(); } foreach ($optimizations[$name]['optimized_value'] as $name => $action) { $res = $this->wp_cli("a2-optimized {$action} {$name}"); } } else { foreach ($optimizations[$name]['deoptimized_value'] as $name => $action) { $res = $this->wp_cli("a2-optimized {$action} {$name}"); } } break; case 'memcached': if ($optimize) { if (!$this->is_using_a2_optimized_cache() && $this->a2_cache_available && !$this->is_w3tc_enabled()) { $this->enable_a2_optimized_cache(); } $this->enable_memcached(); $this->disable_redis(); } else { $this->disable_memcached(); } break; case 'redis': if ($optimize) { $this->enable_redis(); $this->disable_memcached(); } else { $this->disable_redis(); } break; } } } if ($this->is_w3tc_enabled()) { $this->w3tc_keys = $this->get_w3tc_keys($this->contentdir); $this->w3tc_master = $this->get_w3tc_master(); } return $this->get_optimizations(); } public function get_percent_optimized() { //TODO: check for turbocache, a2-optimized, memcached return true or false if optimized or not $optimizations = $this->get_optimizations(); $count = 0; foreach ($optimizations as $name => $optimization) { if ($optimization['optimized']) { $count++; } } return ceil(($count / count($optimizations)) * 100); } public function get_a2_cache_setting($name) { $a2_cache_settings = unserialize($this->get_option('a2opt-cache')); if ($a2_cache_settings && is_array($a2_cache_settings) && isset($a2_cache_settings[$name]) && $a2_cache_settings[$name] == 1) { return true; } else { return false; } } public function set_a2_cache_setting($settings) { $a2_cache_settings = unserialize($this->get_option('a2opt-cache')); foreach ($settings as $name => $value) { $a2_cache_settings[$name] = $value; } $this->set_option('a2opt-cache', serialize($a2_cache_settings)); } public function get_w3tc_key($name) { return $this->w3tc_keys[$name]; } public function get_w3tc_config($name) { return $this->w3tc_master[$name]; } public function get_w3tc_keys($content_dir) { // ensure that if they had w3 Total cache already installed, that it keeps any of their settings that we are not setting // Changed to read from a2-w3-total-cache $keys = []; if ($this->is_w3tc_enabled() && is_dir("{$this->contentdir}/plugins/a2-w3-total-cache")) { if (file_exists("{$content_dir}/plugins/a2-w3-total-cache/lib/W3/ConfigKeys.php")) { $configKeys = str_replace(['<?php', '<?', '?>'], '', file_get_contents("{$content_dir}/plugins/a2-w3-total-cache/lib/W3/ConfigKeys.php")); try { eval($configKeys); } catch (Exception $e) { $this->log_action('Exception caught in get_w3tc_keys ' . $e->getMessage()); } } } return $keys; } public function get_w3tc_master() { //ensure that if they had w3 Total cache already installed, that it keeps any of their settings that we are not setting // Changed to read from a2-w3-total-cache if ($this->is_w3tc_enabled() && is_dir("{$this->contentdir}/plugins/a2-w3-total-cache")) { if (!file_exists("{$this->contentdir}/w3tc-config/master.php")) { return []; } $keys = ''; $config = str_replace(['<?php', '<?', '?>'], '', file_get_contents("{$this->contentdir}/w3tc-config/master.php")); try { $keys = eval($config); } catch (Exception $e) { $this->log_action('Exception caught in get_w3tc_keys ' . $e->getMessage()); $keys = []; } } else { $keys = []; } return $keys; } private function login() { $token = $this->get_login_token(); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, trim($this->get_home_url(), '/') . '/a2_wp_authenticate.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //return the results to a variable curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //skip checks on certs curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //skip checks on certs curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_POSTFIELDS, ['token' => $token]); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf1 = curl_exec($ch); // execute the curl command list($header, $body) = explode("\r\n\r\n", $buf1, 2); preg_match_all('/Set-Cookie: (.*);/', $header, $res);//get the cookies in an array $res $cookies = implode(';', $res[1]);// convert array into cookie format curl_close($ch); return $cookies; } private function save_w3tc($keys) { foreach ($keys as $key => $value) { $val = var_export($value, true); $val = str_replace("'", '"', $val); $command = "eval '\$config = w3_instance(\"W3_Config\"); \$config->set(\"{$key}\",{$val}); \$config->save();'"; //echo $command; $this->wp_cli($command, true); } //set the common.instance_id value in the master.php file $this->wp_cli("eval '\$config = w3_instance(\"W3_Config\"); \$config->set(\"common.instance_id\",mt_rand()); \$config->save();'", true); $this->wp_cli("eval '\$_SERVER[\"SERVER_SOFTWARE\"] = \"Apache\"; \$pgcache = w3_instance(\"W3_AdminEnvironment\"); \$config = w3_instance(\"W3_Config\"); \$pgcache->fix_in_wpadmin(\$config,true);'", true); } public function unset_w3tc_memcached_keys($content_dir) { if ($w3tc_keys = $this->get_w3tc_keys($content_dir)) {//if the file exists and is not null //store a list of variables that are to be edited to be able to check if they exist in one loop //if the item is an array, it will append //if the item is an object it will be converted into an array and completely replace an array //if an item is a string or bool or int: it will replace the value $w3tc_vars = [ 'pgcache.engine' => 'file_generic', 'minify.engine' => 'file', 'dbcache.engine' => 'file', 'objectcache.engine' => 'file' ]; $this->save_w3tc($w3tc_vars); //$this->write_w3tc_master($w3tc_vars, $w3tc_keys, $content_dir); } } private function set_w3tc_memcached_keys() { if (!$this->is_w3tc_enabled()) { $this->enable_w3tc(); } $w3tc_vars = [ 'objectcache.memcached.servers' => $this->memcached_socket, 'dbcache.memcached.servers' => $this->memcached_socket, 'pgcache.memcached.servers' => $this->memcached_socket, 'fragmentcache.memcached.servers' => $this->memcached_socket, 'minify.memcached.servers' => $this->memcached_socket, 'pgcache.check.domain' => true, 'pgcache.prime.post.enabled' => true, 'pgcache.reject.logged' => true, 'pgcache.reject.request_head' => true, 'pgcache.purge.front_page' => true, 'pgcache.purge.home' => true, 'pgcache.purge.post' => true, 'pgcache.purge.comments' => true, 'pgcache.purge.author' => true, 'pgcache.purge.terms' => true, 'pgcache.purge.archive.daily' => true, 'pgcache.purge.archive.monthly' => true, 'pgcache.purge.archive.yearly' => true, 'pgcache.purge.feed.blog' => true, 'pgcache.purge.feed.comments' => true, 'pgcache.purge.feed.author' => true, 'pgcache.purge.feed.terms' => true, 'pgcache.cache.feed' => true, 'pgcache.debug' => true, 'pgcache.purge.postpages_limit' => 0,//purge all pages that list posts 'minify.debug' => true, 'dbcache.debug' => true, 'objectcache.debug' => true, 'mobile.enabled' => true, 'minify.enabled' => true, 'minify.auto' => false, 'minify.engine' => 'memcached', 'minify.html.enable' => true, 'minify.html.engine' => 'html', 'minify.html.inline.css' => true, 'minify.html.inline.js' => true, 'minify.js.enable' => true, 'minify.js.engine' => 'js', 'minify.css.enable' => true, 'minify.css.engine' => 'css', 'minify.js.header.embed_type' => 'nb-js', 'minify.js.body.embed_type' => 'nb-js', 'minify.js.footer.embed_type' => 'nb-js', 'minify.lifetime' => 14400, 'minify.file.gc' => 144000, 'dbcache.enabled' => true, 'dbcache.engine' => 'memcached', 'dbcache.lifetime' => 3600, 'dbcache.file.gc' => 7200, 'objectcache.enabled' => true, 'objectcache.engine' => 'memcached', 'objectcache.lifetime' => 3600, 'objectcache.file.gc' => 7200, 'browsercache.enabled' => true, 'browsercache.cssjs.last_modified' => true, 'browsercache.cssjs.compression' => true, 'browsercache.cssjs.expires' => true, 'browsercache.cssjs.lifetime' => 31536000, 'browsercache.cssjs.nocookies' => false, 'browsercache.cssjs.cache.control' => true, 'browsercache.cssjs.cache.policy' => 'cache_maxage', 'browsercache.cssjs.etag' => true, 'browsercache.cssjs.w3tc' => true, 'browsercache.cssjs.replace' => true, 'browsercache.html.compression' => true, 'browsercache.html.last_modified' => true, 'browsercache.html.expires' => true, 'browsercache.html.lifetime' => 3600, 'browsercache.html.cache.control' => true, 'browsercache.html.cache.policy' => 'cache_maxage', 'browsercache.html.etag' => true, 'browsercache.html.w3tc' => true, 'browsercache.html.replace' => true, 'browsercache.other.last_modified' => true, 'browsercache.other.compression' => true, 'browsercache.other.expires' => true, 'browsercache.other.lifetime' => 31536000, 'browsercache.other.nocookies' => false, 'browsercache.other.cache.control' => true, 'browsercache.other.cache.policy' => 'cache_maxage', 'browsercache.other.etag' => true, 'browsercache.other.w3tc' => true, 'browsercache.other.replace' => true, 'config.check' => true, 'varnish.enabled' => false ]; $this->save_w3tc($w3tc_vars); } protected function get_table($name = 'options') { if ($name == '') { return ''; } $var = "{$this->dbprefix}{$name}"; $table = ''; $stmt = $this->pdo->prepare('SHOW Tables LIKE ?'); $stmt->execute([$var]); if ($stmt->rowCount() == 1 && $res = $stmt->fetchAll()) { $table = $res[0][0]; } else { $var = "%{$name}"; $stmt = $this->pdo->prepare('SHOW Tables LIKE ?'); $stmt->execute([$var]); if ($stmt->rowCount() == 1 && $res = $stmt->fetchAll()) { $table = $res[0][0]; } } return $table; } public function enable_memcached() { if ($this->is_w3tc_enabled() || !$this->a2_cache_available) { // This user either still has W3 Total Cache enabled, or has not updated to the new version of A2 Optimized yet if (!$this->is_w3tc_enabled()) { $this->enable_w3tc(); } if (!isset($this->app->swiftcache) || !isset($this->app->swiftcache->memcached) || !isset($this->app->swiftcache->memcached->id) || !isset($this->app->swiftcache->memcached->user)) { $this->error('The memcached info was missing'); } $memcached = new MemcachedInstance($this->app->swiftcache->memcached->id, $this->app->swiftcache->memcached->user); $this->memcached_instance = $memcached->get_instance(); $this->memcached_socket = $this->memcached_instance->socket_path; $this->set_w3tc_memcached_keys(); $this->flush_cache(); $this->app->swiftcache->memcached->enabled = true; } else { if (!isset($this->app->swiftcache) || !isset($this->app->swiftcache->memcached) || !isset($this->app->swiftcache->memcached->id) || !isset($this->app->swiftcache->memcached->user)) { $this->error('The memcached info was missing'); } $memcached = new MemcachedInstance($this->app->swiftcache->memcached->id, $this->app->swiftcache->memcached->user); $this->memcached_instance = $memcached->get_instance(); $this->memcached_socket = $this->memcached_instance->socket; $this->wp_cli('a2-optimized enable object_cache'); $this->wp_cli("a2-optimized memcached_server '" . $this->memcached_socket . "'"); $this->flush_cache(); $this->app->swiftcache->memcached->enabled = true; } } public function is_redis_enabled() { if ( $this->is_litespeed_enabled() && $this->get_option('litespeed.conf.object') == '1' && $this->get_option('litespeed.conf.object-kind') == '1' && isset($this->app->swiftcache) && isset($this->app->swiftcache->memcached) ) { $this->app->swiftcache->memcached->redis_enabled = true; return true; } return false; } public function is_redis_available() { if ( file_exists('/opt/redis/conf/example.conf') && isset($this->app->swiftcache) && isset($this->app->swiftcache->memcached) ) { $this->app->swiftcache->memcached->redis_availble = true; return true; } return false; } public function enable_redis() { /* Enable Redis extension for all PHP versions */ $username = escapeshellarg($this->username); $php_versions = [ '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1' ]; foreach ($php_versions as $php_ver) { shell_exec("/usr/bin/selectorctl --interpreter=php --enable-user-extensions=redis --user={$username} --version={$php_ver}"); } touch('/home/' . $this->username . '/.redis.on'); // Create flag file for watcher script to create redis socket $redis_socket = '/home/' . $this->username . '/.redis/redis.sock'; $this->wp_cli('plugin install litespeed-cache --activate'); $this->wp_cli('litespeed-option set object true'); // Enable object cache $this->wp_cli('litespeed-option set object-kind 1'); // Set object cache to Redis $this->wp_cli("litespeed-option set object-host '" . $redis_socket . "'"); // Socket path $this->wp_cli('litespeed-option set object-port 0'); // Port is 0 for socket connections $this->wp_cli('option update a2_object_cache_enabled 1'); // Flag that we have this enabled $this->wp_cli("option update a2_optimized_redis_server '" . $redis_socket . "'"); $this->wp_cli('option update a2_optimized_objectcache_type redis'); $this->app->swiftcache->memcached->redis_enabled = true; } public function disable_redis() { $this->wp_cli('litespeed-option set object 0'); // Enable object cache $this->wp_cli('litespeed-option set object-kind 0'); // Set object cache to Redis $this->wp_cli('option update a2_object_cache_enabled 0'); // Flag that we have this enabled $this->wp_cli('option update a2_optimized_objectcache_type memcached'); $this->app->swiftcache->memcached->redis_enabled = false; } public function log_error($error) { error_log($error, 3, "{$this->path}/.a2cp_log"); } public function enable_w3tc() { if (is_dir($this->contentdir)) { if (!(is_dir("{$this->contentdir}/w3tc-config") && is_dir("{$this->contentdir}/plugins/a2-w3-total-cache"))) { $res = $this->wp_cli('plugin install http://wp-plugins.a2hosting.com/wp-content/uploads/rkv-repo/a2-w3-total-cache.zip'); } $res = $this->wp_cli('plugin activate a2-w3-total-cache'); } else { $this->error('there was an error finding the WP_CONTENT_DIR.'); } } public function enable_a2_optimized_cache() { if (is_dir($this->contentdir)) { if (!is_dir("{$this->contentdir}/plugins/a2-optimized-wp")) { $res = $this->wp_cli('plugin install a2-optimized-wp'); } if (!$this->a2_optimized) { $res = $this->wp_cli('plugin activate a2-optimized-wp'); } $res = $this->wp_cli('a2-optimized enable page_cache'); $this->a2_optimized = $this->is_a2_optimized_activated(); $this->a2_cache_available = $this->a2_optimized; } else { $this->error('there was an error finding the WP_CONTENT_DIR.'); } } public function change_admin_password($password) { $table = $this->get_table('users'); $user_id = -1; $user_login = ''; $stmt = $this->mysqli->prepare("select ID,user_login from {$table} where user_status=0 order by ID limit 1"); $stmt->execute(); $stmt->bind_result($user_id, $user_login); $stmt->store_result(); if ($stmt->num_rows > 0) { $stmt->fetch(); } $stmt->close(); if ($user_id != -1) { chdir($this->path); $user_id = escapeshellarg($user_id); $password = escapeshellarg($password); $res = $this->wp_cli("user update {$user_id} --user_pass='{$password}'"); } else { $this->error('There was no administrator found to edit.'); } return $user_login; } public function disable_memcached() { if (is_dir($this->contentdir)) { if ($this->is_w3tc_enabled()) { if (is_dir("{$this->contentdir}/w3tc-config")) { if (is_dir("{$this->contentdir}/plugins/a2-w3-total-cache")) { $this->unset_w3tc_memcached_keys($this->contentdir); $this->flush_cache(); $this->app->swiftcache->memcached->enabled = false; } } } if ($this->is_using_a2_optimized_cache()) { $this->wp_cli('a2-optimized disable object_cache'); $this->flush_cache(); $this->app->swiftcache->memcached->enabled = false; } } else { $this->error('there was an error finding the WP Content Directory.'); } } public function optimize() { if ($this->litespeed) { $this->install_module(); if (!$this->is_using_a2_optimized_cache()) { $this->enable_a2_optimized_cache(); } } $optimizations = $this->get_optimizations(); foreach ($optimizations as $name => $optimization) { $this->set_optimization($name, true, false);//don't save w3tc until the end for performance reasons } } public function install_module() { /* Clear existing caches */ $this->wp_cli('a2-optimized page_cache disable'); $this->wp_cli('w3-total-cache flush all'); $this->wp_cli('a2-w3-total-cache flush all'); $this->wp_cli('cache flush all'); $this->wp_cli('plugin install litespeed-cache --activate'); $this->is_litespeed_enabled = true; $this->app->swiftcache->turbocache->enabled = true; } public function wp_config_has_memcached_server($memcached_server = '127.0.0.1:11211') { $lines = explode(PHP_EOL, $this->config_file_contents); foreach ($lines as $line) { if (strpos($line, 'MEMCACHED_SERVERS') !== false && strpos($line, $memcached_server) !== false) { return true; } } return false; } public function is_memcached_enabled() { if ($this->is_w3tc_enabled()) { if (file_exists("{$this->contentdir}/w3tc-config/master.php")) { if (preg_match('/([\'"]dbcache\.engine[\'"].*=>.*[\'"]memcached[\'"])/iU', file_get_contents("{$this->contentdir}/w3tc-config/master.php"))) { if (preg_match('/([\'"]dbcache\.enabled[\'"].*=>.*true)/iU', file_get_contents("{$this->contentdir}/w3tc-config/master.php"))) { return true; } } } } if ($this->a2_optimized) { $object_cache_file = file_exists("{$this->contentdir}/object-cache.php"); $object_caching_enabled = $this->get_option('a2_object_cache_enabled'); $wp_memcached_server = $this->wp_config_has_memcached_server($this->get_memcached_socket()); if ( $object_cache_file && $object_caching_enabled == 1 && $wp_memcached_server ) { return true; } } return false; } public function is_litespeed_enabled() { $res = $this->wp_cli('plugin status | grep litespeed'); if (strpos($res, 'A litespeed-cache') === false && strpos($res, 'N litespeed-cache') === false) { return false; } $this->is_litespeed_enabled = true; return true; } public function get_memcached_socket() { if (!isset($this->app->swiftcache) || !isset($this->app->swiftcache->memcached) || !isset($this->app->swiftcache->memcached->id) || !isset($this->app->swiftcache->memcached->user)) { return false; } $memcached = new MemcachedInstance($this->app->swiftcache->memcached->id, $this->app->swiftcache->memcached->user); $this->memcached_instance = $memcached->get_instance(); return $this->memcached_instance->socket; } public function backup($exclude_dirs = []) { $this->wp_cli('plugin install duplicator --activate'); $cookies = $this->login(); //$hash = md5(uniqid("", true)); $name = date('Ymdhis') . '_site'; $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//return the results to a variable curl_setopt($ch, CURLOPT_COOKIE, $cookies);//set the cookies curl_setopt($ch, CURLOPT_REFERER, $this->adminurl ); curl_setopt($ch, CURLOPT_URL, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new1'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf1 = curl_exec($ch); // execute the curl command list($header, $body) = explode("\r\n\r\n", $buf1, 2); if (preg_match("/name=[\"']package-hash[\"'] value=[\"']([0-9a-z]*)[\"']/", $body, $res)) { $hash = $res[1]; } else { return false; } $post_data = [ 'action' => '', 'package-hash' => $hash, 'package-name' => $name, 'package-notes' => 'Generated By A2 Optimized', 'archive-format' => 'ZIP', 'filter-on' => 'on', 'filter-dirs' => implode(';', $exclude_dirs) . ';', 'filter-exts' => 'zip;rar;tar;gz;bz2;7z;', 'dbhost' => '', 'dbport' => '', 'dbname' => '', 'dbuser' => '', 'url-new' => '' ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//return the results to a variable curl_setopt($ch, CURLOPT_COOKIE, $cookies);//set the cookies curl_setopt($ch, CURLOPT_REFERER, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new1' ); curl_setopt($ch, CURLOPT_URL, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new2'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf2 = curl_exec($ch); // execute the curl command //list($header, $body) = explode("\r\n\r\n", $buf2, 2); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//return the results to a variable curl_setopt($ch, CURLOPT_COOKIE, $cookies);//set the cookies curl_setopt($ch, CURLOPT_REFERER, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new2' ); curl_setopt($ch, CURLOPT_URL, trim($this->adminurl, '/') . '/admin-ajax.php'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, ['action' => 'duplicator_package_scan']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf3 = curl_exec($ch); list($header, $body) = explode("\r\n\r\n", $buf3, 2); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//return the results to a variable curl_setopt($ch, CURLOPT_COOKIE, $cookies);//set the cookies curl_setopt($ch, CURLOPT_REFERER, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new2' ); curl_setopt($ch, CURLOPT_URL, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new3'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf4 = curl_exec($ch); list($header, $body) = explode("\r\n\r\n", $buf4, 2); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//return the results to a variable curl_setopt($ch, CURLOPT_COOKIE, $cookies);//set the cookies curl_setopt($ch, CURLOPT_REFERER, trim($this->adminurl, '/') . '/admin.php?page=duplicator&tab=new3' ); curl_setopt($ch, CURLOPT_URL, trim($this->adminurl, '/') . '/admin-ajax.php'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_TIMEOUT, 600); curl_setopt($ch, CURLOPT_POSTFIELDS, ['action' => 'duplicator_package_build']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_HEADER, 1); $buf5 = curl_exec($ch); //list($header, $body) = explode("\r\n\r\n", $buf5, 2); return "{$this->homeurl}/wp-snapshots/{$name}_{$hash}_archive.zip"; } public function get_turbocache_defaults() { return [ 'reject_urls' => [ 'admin', 'register', 'login', 'cart', 'checkout', 'addons', 'my-account' ], 'reject_cookies' => [ 'logged_in', 'comment_author', 'wp-postpass', 'w3tc_logged_out', 'wordpress_logged_in', 'wptouch_switch_toggle' ], 'time' => '15 Minutes', 'ttl' => 900, 'enabled' => true ]; } public function stage($url) { $this->sqlfile = $this->dump_database(); } public function dump_database() { if (is_dir($this->app->path) && isset($this->db_user) && isset($this->db_name) && isset($this->db_host) && isset($this->db_password) ) { $timestamp = time(); $this->sqlfile = "{$this->db_name}-{$timestamp}.sql"; $this->su_exec("mysqldump --user={$this->db_user} --password={$this->db_password} --host={$this->db_host} {$this->db_name} > {$this->home}/{$sqlfile}"); } return $this->sqlfile; } private function find_replace_database($file) { } } Save