%PDF- %PDF-
Direktori : /var/www/businessmultisite/wp-content/plugins/wpsynchro/includes/REST/ |
Current File : /var/www/businessmultisite/wp-content/plugins/wpsynchro/includes/REST/HealthCheck.php |
<?php namespace WPSynchro\REST; use WPSynchro\CommonFunctions; use WPSynchro\Masterdata\MasterdataRetrieval; use WPSynchro\Transport\TransferToken; use WPSynchro\Transport\TransferAccessKey; use WPSynchro\REST\MasterData; use WPSynchro\Logger\NullLogger; use WPSynchro\Initiate\InitiateTokenRetrieval; use WPSynchro\InstallationFactory; use WPSynchro\Licensing; use WPSynchro\Transport\BasicAuth; use WPSynchro\Transport\Destination; /** * Class for handling REST service "healthcheck" * Call should already be verified by permissions callback * * @since 1.1 */ class HealthCheck { public $healthcheck_errors; private $healthcheck_documentation_url = 'https://wpsynchro.com/documentation/health-check-errors'; public function __construct() { $this->healthcheck = new \stdClass(); $this->healthcheck->errors = []; $this->healthcheck->warnings = []; } public function service($request) { global $wpdb; // Get methods and execute the tests $check_methods = $this->getTestFunctions(); foreach ($check_methods as $method) { $this->$method(); if (count($this->healthcheck->errors) > 0) { break; } } // If no errors or warnings, set timestamp in database if (count($this->healthcheck->errors) == 0) { update_site_option("wpsynchro_healthcheck_timestamp", time()); } return new \WP_REST_Response($this->healthcheck, 200); } /** * Get functions to test */ public function getTestFunctions() { // Find test functions $class_methods = get_class_methods($this); $check_methods = []; foreach ($class_methods as $method) { if (strpos($method, 'check') === 0) { $check_methods[] = $method; } } return $check_methods; } /** * Check environment, WP/PHP/SQL */ public function checkEnvironment() { $commonfunctions = new CommonFunctions(); $errors_from_env = $commonfunctions->checkEnvCompatability(); if (count($errors_from_env) > 0) { $this->healthcheck->errors = array_merge($this->healthcheck->errors, $errors_from_env); } } /** * Check that database is current, but not newer */ public function checkDatabaseIsCurrent() { $dbversion = get_option('wpsynchro_dbversion'); if (!$dbversion || $dbversion == "") { $dbversion = 0; } if ($dbversion > WPSYNCHRO_DB_VERSION) { $this->healthcheck->errors[] = __("WP Synchro database version is newer than the currently installed plugin version - Please upgrade plugin to newest version - Continue at own risk", "wpsynchro"); } } /** * Check that local installation has access key set */ public function checkAccessKeyIsSet() { $accesskey = TransferAccessKey::getAccessKey(); if (strlen(trim($accesskey)) < 20) { $this->healthcheck->errors[] = __("Access key for this site is not set - This needs to be configured for WP Synchro to work.", "wpsynchro"); } } /** * Check proper PHP extensions */ public function checkPHPExtensions() { $required_php_extensions = ["curl", "mbstring", "openssl", "mysqli"]; $php_extensions_loaded = get_loaded_extensions(); $missing_extensions = []; foreach ($required_php_extensions as $required_php_extension) { if (!in_array($required_php_extension, $php_extensions_loaded)) { $missing_extensions[] = $required_php_extension; } } if (count($missing_extensions) > 0) { $this->healthcheck->errors[] = sprintf(__("Missing PHP extensions for WP Synchro to work. Enable extension(s) '%s' to php.ini and reload.", "wpsynchro"), implode(", ", $missing_extensions)); } } /** * Check that sql max_allowed_packet is set to something proper */ public function checkSQLMaxAllowPacket() { global $wpdb; $max_allowed_packet = (int) $wpdb->get_row("SHOW VARIABLES LIKE 'max_allowed_packet'")->Value; if ($max_allowed_packet < 1024) { $this->healthcheck->errors[] = sprintf( __("Your database server is misconfigured - The setting 'max_allowed_packet' is too low. It is currently set to: %d. Check out the documentation for the SQL server you are using and correct this setting.", "wpsynchro"), $max_allowed_packet ); } } /** * Check that permalink structure is NOT plain */ public function checkPermalinkStructure() { $permalink_structure = get_option('permalink_structure'); if (trim($permalink_structure) == "") { $this->healthcheck->errors[] = __("Plain permalinks is not supported in WP Synchro. You should change it to %postname% instead", "wpsynchro"); } } /** * Check that SAVEQUERIES are not active */ public function checkSaveQueries() { if (defined("SAVEQUERIES") && SAVEQUERIES == true) { $this->healthcheck->errors[] = __("SAVEQUERIES constant is set. This is normally only for debugging. It will generate out of memory errors with WP Synchro synchronizations", "wpsynchro"); } } /** * Check license okay, if PRO */ public function checkLicenseIfPRO() { if (\WPSynchro\CommonFunctions::isPremiumVersion()) { $licensing = new Licensing(); if ($licensing->hasProblemWithLicensing()) { $this->healthcheck->errors[] = $licensing->getLicenseErrorMessage(); } } } /** * Check that multiple connections to local services can be done - LocalWP problems most of time or misconfigured hosting */ public function checkMultipleConnections($http_type = 'GET') { $multiple_connection_test_url = get_rest_url(null, '/wpsynchro/v1/test/'); $args = [ 'method' => $http_type, 'redirection' => 0, 'timeout' => 5, 'sslverify' => false, 'headers' => [], ]; // Check for basic auth setup $destination = new Destination(Destination::LOCAL); $destination_basic_auth = $destination->getBasicAuthentication(); if ($destination_basic_auth !== false) { $args["headers"]["Authorization"] = "Basic " . base64_encode($destination_basic_auth[0] . ":" . $destination_basic_auth[1]); } $tests_per_http_type = 5; $error_runs = []; for ($i = 0; $i < $tests_per_http_type; $i++) { if ($http_type == 'GET') { $response = wp_remote_get($multiple_connection_test_url, $args); } elseif ($http_type == 'POST') { $response = wp_remote_post($multiple_connection_test_url, $args); } $response_code = wp_remote_retrieve_response_code($response); if ($response_code === 200) { // Check correct body $body = wp_remote_retrieve_body($response); if ($body != '[]') { $error_runs[$i] = $response; } } else { $error_runs[$i] = $response; } } if (count($error_runs) > 0) { $this->healthcheck->errors[] = sprintf( __("REST test error - Tried making %d consecutive requests (with HTTP %s) to a test REST service on this site. %d of them failed, with these errors:", "wpsynchro"), $tests_per_http_type, $http_type, count($error_runs) ); // Get basic auth class, to check if we are hitting basic auth $basic_auth = new BasicAuth(); $atleast_one_used_basic_auth = false; foreach ($error_runs as $error_run_num => $response) { if (is_wp_error($response)) { $this->healthcheck->errors[] = sprintf(__("Error from request (number %d):", "wpsynchro"), $error_run_num + 1) . " " . $response->get_error_message(); } else { // Check for authentication on remote if ($basic_auth->checkResponseHeaderForBasicAuth($response)) { $atleast_one_used_basic_auth = true; $this->healthcheck->errors[] = __("This site is protected by Basic Authentication, which requires a username and password. You can add the correct username/password in the 'Setup' menu.", "wpsynchro"); break; } // Maybe a content error $body = wp_remote_retrieve_body($response); if ($body != '[]') { $this->healthcheck->errors[] = sprintf(__("Error from request (number %d) - Got wrong data in response from webservice - Expected '[]' - Got: ", "wpsynchro"), $error_run_num + 1) . " '" . $body . "'"; } } } if ($atleast_one_used_basic_auth === false) { // Catch LocalWP bug if (isset($error_runs[1]) && isset($error_runs[3]) && count($error_runs) === 2) { $this->healthcheck->errors[] = __("The pattern of errors suggest you are using LocalWP as development environment. It contains a bug where 50% of remote requests fail, when called from the code. That is why request 2 and 4 fails, but 1,3 and 5 succeed. Read more on https://wpsynchro.com/documentation/local-by-flywheel-localwp", "wpsynchro"); } else { $this->healthcheck->errors[] = sprintf( __("This issue is most likely caused by a misconfiguration of the hosting environment. Most often because of too few available worker processes. See more documentation on this here: %s", "wpsynchro"), $this->healthcheck_documentation_url ); } } } } /** * Check that multiple connections to local services can be done via POST */ public function checkMultipleConnectionsPOST() { $this->checkMultipleConnections('POST'); } /** * Check local REST urls for connectivity and proper response */ public function checkInitiateAndMastedata() { $initiate_token = ""; $initiate_server_okay = false; $logger = new NullLogger(); $destination = new Destination(Destination::LOCAL); $retrieval = new InitiateTokenRetrieval($logger, $destination, "local"); $result = $retrieval->getInitiateToken(); if ($result && isset($retrieval->token) && strlen($retrieval->token) > 0) { $initiate_token = $retrieval->token; $initiate_server_okay = true; } else { $this->healthcheck->errors = array_merge($this->healthcheck->errors, $retrieval->getErrors()); $this->healthcheck->warnings = array_merge($this->healthcheck->warnings, $retrieval->getWarnings()); $this->healthcheck->errors[] = __("REST error - Can not reach 'initiate' REST service - Check that REST services is accessible and not being blocked", "wpsynchro"); } if ($initiate_server_okay) { // Create a transfer token based on the token we just got $transfer_token = TransferToken::getTransferToken(TransferAccessKey::getAccessKey(), $initiate_token); // Get masterdata retrival object $retrieval = new MasterdataRetrieval($destination); $retrieval->setDataToRetrieve(['dbtables', 'filedetails']); $retrieval->setToken($transfer_token); $retrieval->setEncryptionKey(TransferAccessKey::getAccessKey()); $result = $retrieval->getMasterdata(); // Check for errors if ($result) { if (!$retrieval->data->dbtables) { $this->healthcheck->errors[] = __("REST error - Masterdata REST service returns improper response - Data was not returned in usable way - Check PHP error log", "wpsynchro"); } } else { $this->healthcheck->errors[] = __("REST error - Can not reach 'masterdata' REST service - Check that WP Synchro is activated and REST service accessible", "wpsynchro"); } } } /** * Check writable log directory */ public function checkWritableLogDir() { $commonfunctions = new CommonFunctions(); $commonfunctions->createLogLocation(); $log_location = $commonfunctions->getLogLocation(); $log_dir = realpath($log_location); if (!is_writable($log_dir)) { $this->healthcheck->errors[] = sprintf(__("WP Synchro log dir is not writable for PHP - Path: %s ", "wpsynchro"), $log_dir); } } /** * Check other relevant dir for writability (typically for files sync) */ public function checkRelevantDirsForWritable() { if (!\WPSynchro\CommonFunctions::isPremiumVersion()) { return; } $paths_check = [ // Document root $_SERVER['DOCUMENT_ROOT'], // Absolut directory of WP_CONTENT folder, or whatever it is called WP_CONTENT_DIR, // One dir above webroot dirname(realpath($_SERVER['DOCUMENT_ROOT'])) ]; foreach ($paths_check as $path) { if (!MasterData::checkReadWriteOnDir($path)) { $this->healthcheck->warnings[] = sprintf(__("Path that WP Synchro might use for synchronization is not writable- Path: %s - This can be caused by PHP's open_basedir setting or file permissions", "wpsynchro"), $path); } } } }