| 1 |
<?php |
| 2 |
|
| 3 |
class WooMailerLiteAdminWizardController extends WooMailerLiteController |
| 4 |
{ |
| 5 |
|
| 6 |
public function handleConnectAccount() |
| 7 |
{ |
| 8 |
$this->authorize()->validate(['apiKey' => ['required', 'string']]); |
| 9 |
if (!WooMailerLiteCache::get('table_check')) { |
| 10 |
WooMailerLiteMigration::migrate(); |
| 11 |
WooMailerLiteCache::set('table_check', true, 86400); |
| 12 |
} |
| 13 |
$response = $this->apiClient($this->validated['apiKey'])->validateKey($this->validated['apiKey']); |
| 14 |
if ($response->success) { |
| 15 |
WooMailerLiteCache::set('valid_api', true, 86400); |
| 16 |
WooMailerLiteOptions::updateMultiple([ |
| 17 |
'apiKey' => $this->validated['apiKey'], |
| 18 |
'wizardStep' => 1, |
| 19 |
]); |
| 20 |
if ($this->apiClient()->isClassic()) { |
| 21 |
$response->data = $response->data->account; |
| 22 |
} |
| 23 |
WooMailerLiteOptions::updateMultiple([ |
| 24 |
'accountName' => $response->data->name, |
| 25 |
'accountId' => $response->data->id, |
| 26 |
'accountSubdomain' => $response->data->subdomain ?? '' |
| 27 |
]); |
| 28 |
$response->addData('mlPlatform', $this->apiClient()->getApiType()); |
| 29 |
} |
| 30 |
|
| 31 |
return $this->response($response, $response->status); |
| 32 |
} |
| 33 |
|
| 34 |
public function getGroups() |
| 35 |
{ |
| 36 |
$this->authorize(); |
| 37 |
$params = [ |
| 38 |
'limit' => 50, |
| 39 |
'page' => $this->request('page') ?? 1, |
| 40 |
]; |
| 41 |
|
| 42 |
if ($this->requestHas('page') && ($this->request['page'] !== '1')) { |
| 43 |
$params['offset'] = ($this->request['page'] - 1) * $params['limit']; |
| 44 |
} |
| 45 |
|
| 46 |
if ($this->requestHas('filter')) { |
| 47 |
$params['filter'] = [ |
| 48 |
'name' => $this->request('filter') |
| 49 |
]; |
| 50 |
if ($this->apiClient()->isClassic()) { |
| 51 |
$params['filters'] = ['name' => ['$like' => '%' . $this->request['filter'] . '%']]; |
| 52 |
} |
| 53 |
} |
| 54 |
$response = $this->apiClient()->getGroups($params); |
| 55 |
$groups = []; |
| 56 |
if ($response->success) { |
| 57 |
if (isset($response->data) && is_array($response->data)) { |
| 58 |
foreach ($response->data as $group) { |
| 59 |
$groups['data'][] = [ |
| 60 |
'id' => $group->id, |
| 61 |
'name' => $group->name |
| 62 |
]; |
| 63 |
} |
| 64 |
} |
| 65 |
if ($response->links && isset($response->links->next)) { |
| 66 |
$groups['pagination'] = [ |
| 67 |
'next' => (bool)$response->links->next |
| 68 |
]; |
| 69 |
} elseif ($this->apiClient()->isClassic() && (isset($groups['data']) && count($groups['data']) > 0)) { |
| 70 |
$groups['pagination'] = [ |
| 71 |
'next' => !empty($groups) |
| 72 |
]; |
| 73 |
} |
| 74 |
} |
| 75 |
return $this->response(!empty($groups) ? $groups : $response, $response->status); |
| 76 |
} |
| 77 |
|
| 78 |
public function shopSetup() |
| 79 |
{ |
| 80 |
$this->authorize()->validate([ |
| 81 |
'group' => ['required', 'string'], |
| 82 |
'syncFields' => ['required', 'array'], |
| 83 |
'consumerKey' => ['sometimes', 'string'], |
| 84 |
'consumerSecret' => ['sometimes', 'string'] |
| 85 |
]); |
| 86 |
|
| 87 |
// temp removing checking keys |
| 88 |
// if (!$this->apiClient()->isReWrite() && !$this->validateClassicConsumerKeys($this->request['consumerKey'], $this->request['consumerSecret'])) { |
| 89 |
// return $this->response(['message' => 'Invalid consumer key or secret'], 400); |
| 90 |
// } |
| 91 |
|
| 92 |
if (!WooMailerLiteOptions::get('group') || (!empty(WooMailerLiteOptions::get('group', [])) && WooMailerLiteOptions::get('group')['id'] != $this->validated['group'])) { |
| 93 |
$response = $this->apiClient()->getGroupById($this->validated['group']); |
| 94 |
if (!$response->success) { |
| 95 |
return $this->response($response, $response->status); |
| 96 |
} |
| 97 |
WooMailerLiteOptions::update('group', ['id' => $response->data->id, 'name' => $response->data->name]); |
| 98 |
} |
| 99 |
|
| 100 |
$shopName = get_bloginfo('name'); |
| 101 |
$shopName = !empty($shopName) ? $shopName : home_url(); |
| 102 |
$shopId = WooMailerLiteOptions::get('shopId'); |
| 103 |
$popupsEnabled = WooMailerLiteOptions::get('popupsEnabled'); |
| 104 |
$currency = get_option('woocommerce_currency'); |
| 105 |
$store = home_url(); |
| 106 |
if ($this->apiClient()->isReWrite()) { |
| 107 |
if ($shopId === false) { |
| 108 |
$shops = $this->apiClient()->getShops(); |
| 109 |
if ($shops->success) { |
| 110 |
foreach ($shops->data as $shop) { |
| 111 |
if ($shop->url == home_url()) { |
| 112 |
$shopId = $shop->id; |
| 113 |
WooMailerLiteOptions::update('shopId', $shopId); |
| 114 |
break; |
| 115 |
} |
| 116 |
} |
| 117 |
} |
| 118 |
} |
| 119 |
$data = [ |
| 120 |
'name' => $shopName, |
| 121 |
'url' => $store, |
| 122 |
'currency' => $currency, |
| 123 |
'platform' => 'woocommerce', |
| 124 |
'group_id' => $this->validated['group'], |
| 125 |
'enable_popups' => $popupsEnabled, |
| 126 |
'enable_resubscribe' => $this->request('resubscribe'), |
| 127 |
'enabled' => true, |
| 128 |
'access_data' => '-' |
| 129 |
]; |
| 130 |
} else { |
| 131 |
$data = [ |
| 132 |
'consumer_key' => $this->validated['consumerKey'], |
| 133 |
'consumer_secret' => $this->validated['consumerSecret'], |
| 134 |
'store' => $store, |
| 135 |
'currency' => $currency, |
| 136 |
'group_id' => $this->validated['group'], |
| 137 |
'resubscribe' => $this->request('resubscribe') ?? 0, |
| 138 |
'ignore_list' => $this->request('ignoreList') ?? '', |
| 139 |
'create_segments' => $this->request('createSegments') ?? '' |
| 140 |
]; |
| 141 |
} |
| 142 |
|
| 143 |
$this->apiClient()->toggleShop($store, 1); |
| 144 |
$response = $this->apiClient()->setConsumerData($data); |
| 145 |
|
| 146 |
if ($response->success) { |
| 147 |
WooMailerLiteOptions::updateMultiple([ |
| 148 |
'wizardStep'=> 2, |
| 149 |
'shopId' => $response->data->id, |
| 150 |
'popupsEnabled' => $response->data->enable_popups, |
| 151 |
'syncFields' => $this->validated['syncFields'], |
| 152 |
'enabled' => true, |
| 153 |
'consumerKey' => $this->validated['consumerKey'] ?? null, |
| 154 |
'consumerSecret' => $this->validated['consumerSecret'] ?? null, |
| 155 |
]); |
| 156 |
if (!$response->data->group) { |
| 157 |
$response->data->group = WooMailerLiteOptions::get('group'); |
| 158 |
} |
| 159 |
WooMailerLiteProductSyncJob::dispatch(); |
| 160 |
} |
| 161 |
$message = ''; |
| 162 |
if (!$response->success) { |
| 163 |
$message = $response->message ?? 'Unable to set up the shop. Please try again.'; |
| 164 |
} |
| 165 |
return $this->response($response, $response->status, $message); |
| 166 |
} |
| 167 |
|
| 168 |
protected function validateClassicConsumerKeys($consumerKey, $consumerSecret) { |
| 169 |
$endpoint = home_url() . '/wp-json/wc/v2/products'; |
| 170 |
$oauth_params = [ |
| 171 |
'oauth_consumer_key' => $consumerKey, |
| 172 |
'oauth_nonce' => uniqid(mt_rand(1, 1000)), |
| 173 |
'oauth_signature_method' => 'HMAC-SHA1', |
| 174 |
'oauth_timestamp' => time(), |
| 175 |
'oauth_version' => '1.0', |
| 176 |
]; |
| 177 |
ksort($oauth_params); |
| 178 |
$base_string = 'GET&' . rawurlencode($endpoint) . '&' . rawurlencode(http_build_query($oauth_params, '', '&', PHP_QUERY_RFC3986)); |
| 179 |
$signing_key = rawurlencode($consumerSecret) . '&'; |
| 180 |
$oauth_params['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $signing_key, true)); |
| 181 |
$url_with_params = $endpoint . '?' . http_build_query($oauth_params); |
| 182 |
|
| 183 |
$ch = curl_init(); |
| 184 |
curl_setopt($ch, CURLOPT_URL, $url_with_params); |
| 185 |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
| 186 |
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); |
| 187 |
|
| 188 |
curl_exec($ch); |
| 189 |
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
| 190 |
if ($http_code == 200) { |
| 191 |
return true; |
| 192 |
} |
| 193 |
return false; |
| 194 |
} |
| 195 |
public function getDebugLogs() |
| 196 |
{ |
| 197 |
$this->authorize(); |
| 198 |
if (!function_exists('shell_exec')) { |
| 199 |
return $this->response(['log' => 'Please enable shell_exec function in your php config.'], 200); |
| 200 |
} |
| 201 |
|
| 202 |
$errorPath = escapeshellarg(ini_get('error_log')); |
| 203 |
$log = ''; |
| 204 |
if(!empty($errorPath)) { |
| 205 |
$log = shell_exec("tail -500 {$errorPath}"); |
| 206 |
} |
| 207 |
|
| 208 |
if(empty($log)) { |
| 209 |
$log_file = ABSPATH . 'wp-content/debug.log'; |
| 210 |
if (file_exists($log_file)) { |
| 211 |
$log = file_get_contents($log_file); |
| 212 |
} |
| 213 |
} |
| 214 |
|
| 215 |
if (empty($log)) { |
| 216 |
$log = 'No logs found'; |
| 217 |
} |
| 218 |
|
| 219 |
return $this->response(['log' => $this->redact($log)], 200); |
| 220 |
} |
| 221 |
|
| 222 |
private function redact($log) |
| 223 |
{ |
| 224 |
$patterns = [ |
| 225 |
'/apiKey["\']?\s*[:=]\s*["\']?[a-zA-Z0-9_-]+["\']?/i' => 'apiKey: [REDACTED]', |
| 226 |
'/api_key["\']?\s*[:=]\s*["\']?[a-zA-Z0-9_-]+["\']?/i' => 'api_key: [REDACTED]', |
| 227 |
'/password["\']?\s*[:=]\s*["\']?[^"\'\s]+["\']?/i' => 'password: [REDACTED]', |
| 228 |
'/consumer_?secret["\']?\s*[:=]\s*["\']?[^"\'\s]+["\']?/i' => 'consumer_secret: [REDACTED]', |
| 229 |
'/consumer_?key["\']?\s*[:=]\s*["\']?[^"\'\s]+["\']?/i' => 'consumer_key: [REDACTED]', |
| 230 |
'/Bearer\s+[a-zA-Z0-9_-]+/i' => 'Bearer [REDACTED]', |
| 231 |
'/Authorization:\s*[^\n]+/i' => 'Authorization: [REDACTED]', |
| 232 |
]; |
| 233 |
|
| 234 |
foreach ($patterns as $pattern => $replacement) { |
| 235 |
$log = preg_replace($pattern, $replacement, $log); |
| 236 |
} |
| 237 |
|
| 238 |
return $log; |
| 239 |
} |
| 240 |
} |
| 241 |
|