| 1 |
<?php |
| 2 |
|
| 3 |
namespace WPSynchro\API; |
| 4 |
|
| 5 |
use WPSynchro\Initiate\InitiateTokenRetrieval; |
| 6 |
use WPSynchro\Masterdata\MasterdataRetrieval; |
| 7 |
use WPSynchro\Logger\NullLogger; |
| 8 |
use WPSynchro\Migration\Job; |
| 9 |
use WPSynchro\Migration\Migration; |
| 10 |
use WPSynchro\Migration\MigrationController; |
| 11 |
use WPSynchro\Transport\Destination; |
| 12 |
use WPSynchro\Transport\RemoteTransport; |
| 13 |
use WPSynchro\Transport\TransferToken; |
| 14 |
use WPSynchro\Transport\TransferAccessKey; |
| 15 |
|
| 16 |
/** |
| 17 |
* Class for handling service "migration/verify" - Verifying and gathering masterdata from both source and target |
| 18 |
*/ |
| 19 |
class VerifyMigration extends WPSynchroService |
| 20 |
{ |
| 21 |
// Service Response |
| 22 |
public $response; |
| 23 |
// Job object |
| 24 |
public $job; |
| 25 |
|
| 26 |
public function __construct() |
| 27 |
{ |
| 28 |
// Generate response |
| 29 |
$this->response = new \stdClass(); |
| 30 |
$this->response->errors = []; |
| 31 |
$this->response->warnings = []; |
| 32 |
$this->response->source_masterdata = []; |
| 33 |
$this->response->target_masterdata = []; |
| 34 |
|
| 35 |
// Set job |
| 36 |
$this->job = new Job(); |
| 37 |
} |
| 38 |
|
| 39 |
public function service() |
| 40 |
{ |
| 41 |
// Get data to check on |
| 42 |
$body = json_decode($this->getRequestBody()); |
| 43 |
$migration = Migration::map($body); |
| 44 |
|
| 45 |
/** |
| 46 |
* Step0: Validate |
| 47 |
*/ |
| 48 |
$this->validate($migration); |
| 49 |
if (count($this->response->errors) > 0) { |
| 50 |
http_response_code(400); |
| 51 |
echo json_encode($this->response); |
| 52 |
return; |
| 53 |
} |
| 54 |
|
| 55 |
/** |
| 56 |
* Step1: Verify that we can connect to url and get a remote token |
| 57 |
*/ |
| 58 |
// Check the headers, to make sure redirects are not done |
| 59 |
$remote_destination = new Destination(Destination::REMOTE); |
| 60 |
$remote_destination->setMigration($migration); |
| 61 |
|
| 62 |
$remotetransport = new RemoteTransport(); |
| 63 |
$remotetransport->setNoRetries(); |
| 64 |
$remotetransport->setNoRedirection(); |
| 65 |
$remotetransport->setDestination($remote_destination); |
| 66 |
$remotetransport->init(); |
| 67 |
$remotetransport->setUrl($remote_destination->getFullURL()); |
| 68 |
$remotetransport->setEncryptionKey($remote_destination->getAccessKey()); |
| 69 |
|
| 70 |
$sync_request_result = $remotetransport->remotePOST(); |
| 71 |
$http_status_code_first = substr($sync_request_result->statuscode, 0, 1); |
| 72 |
|
| 73 |
// Check if headers are 3xx |
| 74 |
if ($http_status_code_first == '3') { |
| 75 |
// Redirect |
| 76 |
$new_location = $sync_request_result->getHeader('location'); |
| 77 |
if ($new_location !== false) { |
| 78 |
$this->response->warnings[] = sprintf(__("The remote URL is responding with a redirect to %s, which may or may not cause problems connecting with WP Synchro API services.", "wpsynchro"), $new_location); |
| 79 |
} else { |
| 80 |
$this->response->warnings[] = __("The remote URL is responding with a redirect http code (3xx) to another url, which may or may not cause problems connecting with WP Synchro API services.", "wpsynchro"); |
| 81 |
} |
| 82 |
} elseif ($http_status_code_first != '2') { |
| 83 |
// Something not in the 2xx range, which is probably an error of some kind |
| 84 |
$this->response->warnings[] = sprintf(__("The remote URL is responding with a non-successful response (HTTP %d), which may or may not cause problems connecting with WP Synchro API services.", "wpsynchro"), $sync_request_result->statuscode); |
| 85 |
} |
| 86 |
|
| 87 |
// Try to fetch initiate token |
| 88 |
$remote_token = $this->doInitiateOnRemote($remote_destination); |
| 89 |
$this->job->remote_transfer_token = TransferToken::getTransferToken($migration->access_key, $remote_token); |
| 90 |
$this->response->remote_transfer_token = $this->job->remote_transfer_token; |
| 91 |
if (count($this->response->errors) > 0) { |
| 92 |
http_response_code(400); |
| 93 |
echo json_encode($this->response); |
| 94 |
return; |
| 95 |
} |
| 96 |
|
| 97 |
/** |
| 98 |
* Step2: Get local transfer token |
| 99 |
*/ |
| 100 |
$local_destination = new Destination(Destination::LOCAL); |
| 101 |
$local_token = $this->doInitiateOnRemote($local_destination); |
| 102 |
$this->job->local_transfer_token = TransferToken::getTransferToken(TransferAccessKey::getAccessKey(), $local_token); |
| 103 |
|
| 104 |
if (count($this->response->errors) > 0) { |
| 105 |
http_response_code(400); |
| 106 |
echo json_encode($this->response); |
| 107 |
return; |
| 108 |
} |
| 109 |
|
| 110 |
/** |
| 111 |
* Set data in job object |
| 112 |
*/ |
| 113 |
$sync_controller = MigrationController::getInstance(); |
| 114 |
$sync_controller->job = $this->job; |
| 115 |
|
| 116 |
if ($migration->type === 'pull') { |
| 117 |
$this->job->from_token = $this->job->remote_transfer_token; |
| 118 |
$this->job->from_accesskey = $migration->access_key; |
| 119 |
$this->job->to_token = $this->job->local_transfer_token; |
| 120 |
$this->job->to_accesskey = TransferAccessKey::getAccessKey(); |
| 121 |
} else { |
| 122 |
$this->job->to_token = $this->job->remote_transfer_token; |
| 123 |
$this->job->to_accesskey = $migration->access_key; |
| 124 |
$this->job->from_token = $this->job->local_transfer_token; |
| 125 |
$this->job->from_accesskey = TransferAccessKey::getAccessKey(); |
| 126 |
} |
| 127 |
if (count($this->response->errors) > 0) { |
| 128 |
http_response_code(400); |
| 129 |
echo json_encode($this->response); |
| 130 |
return; |
| 131 |
} |
| 132 |
|
| 133 |
/** |
| 134 |
* Step3: Get masterdata from remote site |
| 135 |
*/ |
| 136 |
$remote_masterdata = $this->doMasterdataOnRemote($remote_destination, $this->job->remote_transfer_token, $migration->access_key); |
| 137 |
if (count($this->response->errors) > 0) { |
| 138 |
http_response_code(400); |
| 139 |
echo json_encode($this->response); |
| 140 |
return; |
| 141 |
} |
| 142 |
|
| 143 |
/** |
| 144 |
* Step4: Get masterdata from local site |
| 145 |
*/ |
| 146 |
$local_masterdata = $this->doMasterdataOnRemote($local_destination, $this->job->local_transfer_token, TransferAccessKey::getAccessKey()); |
| 147 |
if (count($this->response->errors) > 0) { |
| 148 |
http_response_code(400); |
| 149 |
echo json_encode($this->response); |
| 150 |
return; |
| 151 |
} |
| 152 |
|
| 153 |
/** |
| 154 |
* Set data in response |
| 155 |
*/ |
| 156 |
if ($migration->type === 'pull') { |
| 157 |
$this->response->source_masterdata = $remote_masterdata; |
| 158 |
$this->response->target_masterdata = $local_masterdata; |
| 159 |
} else { |
| 160 |
$this->response->source_masterdata = $local_masterdata; |
| 161 |
$this->response->target_masterdata = $remote_masterdata; |
| 162 |
} |
| 163 |
|
| 164 |
|
| 165 |
echo json_encode($this->response); |
| 166 |
return; |
| 167 |
} |
| 168 |
|
| 169 |
/** |
| 170 |
* Validate input |
| 171 |
*/ |
| 172 |
public function validate(Migration $migration) |
| 173 |
{ |
| 174 |
// Valdidate url |
| 175 |
if (!filter_var($migration->site_url, FILTER_VALIDATE_URL)) { |
| 176 |
$this->response->errors[] = __("The website url does not seem to be valid - Please enter a valid website url", "wpsynchro"); |
| 177 |
} |
| 178 |
// Validate access key |
| 179 |
if (strlen($migration->access_key) < 10) { |
| 180 |
$this->response->errors[] = __("The access key does not seem to be valid - Please enter a valid access key", "wpsynchro"); |
| 181 |
} |
| 182 |
// Validate type |
| 183 |
$allowed_types = ["push", "pull"]; |
| 184 |
if (!in_array($migration->type, $allowed_types)) { |
| 185 |
$this->response->errors[] = __("The type of migration does not seem to be valid - Please choose a valid migration type", "wpsynchro"); |
| 186 |
} |
| 187 |
} |
| 188 |
|
| 189 |
/** |
| 190 |
* Get initiation token from url |
| 191 |
*/ |
| 192 |
public function doInitiateOnRemote(Destination $destination) |
| 193 |
{ |
| 194 |
$logger = new NullLogger(); |
| 195 |
|
| 196 |
$initiate_retrieval = new InitiateTokenRetrieval($logger, $destination, $destination->sync_type); |
| 197 |
$result = $initiate_retrieval->getInitiateToken(); |
| 198 |
|
| 199 |
$initiate_errors = $initiate_retrieval->getErrors(); |
| 200 |
|
| 201 |
$initialize_default_error = sprintf(__("Could not initialize with %s - Check that WP Synchro is installed, connection to the site is not blocked and that health check runs without errors on the site. If basic authentication is enabled on the remote site, make sure connection is set to basic authentication with correct username and password.", "wpsynchro"), $destination->getFullURL()); |
| 202 |
|
| 203 |
if ($result && isset($initiate_retrieval->token) && strlen($initiate_retrieval->token) > 0) { |
| 204 |
return $initiate_retrieval->token; |
| 205 |
} elseif (count($initiate_errors) > 0) { |
| 206 |
$this->response->errors[] = $initialize_default_error; |
| 207 |
foreach ($initiate_errors as $error) { |
| 208 |
$this->response->errors[] = $error; |
| 209 |
} |
| 210 |
} else { |
| 211 |
$this->response->errors[] = $initialize_default_error; |
| 212 |
} |
| 213 |
|
| 214 |
return ""; |
| 215 |
} |
| 216 |
|
| 217 |
/** |
| 218 |
* Get masterdata from remote |
| 219 |
*/ |
| 220 |
public function doMasterdataOnRemote(Destination $destination, $transfer_token, $encryption_key) |
| 221 |
{ |
| 222 |
// Get masterdata retrival object |
| 223 |
$retrieval = new MasterdataRetrieval($destination); |
| 224 |
$retrieval->setDataToRetrieve(['dbtables', 'filedetails']); |
| 225 |
$retrieval->setToken($transfer_token); |
| 226 |
$retrieval->setEncryptionKey($encryption_key); |
| 227 |
$result = $retrieval->getMasterdata(); |
| 228 |
|
| 229 |
if ($result) { |
| 230 |
if (is_object($retrieval->data) && isset($retrieval->data->base)) { |
| 231 |
return $retrieval->data; |
| 232 |
} else { |
| 233 |
$this->response->errors[] = sprintf(__("Tried to get masterdata from %s, but got wrong response. Make sure WP Synchro health check runs without error on both sites.", "wpsynchro"), $destination->getFullURL()); |
| 234 |
return []; |
| 235 |
} |
| 236 |
} else { |
| 237 |
$this->response->errors[] = sprintf(__("Could not get masterdata from %s - Check that WP Synchro is installed, connection to the site is not blocked and that health check runs without errors on the site", "wpsynchro"), $destination->getFullURL()); |
| 238 |
return []; |
| 239 |
} |
| 240 |
} |
| 241 |
} |
| 242 |
|