PluginProbe
MakeCommerce for WooCommerce / 4.1.0
MakeCommerce for WooCommerce v4.1.0
4.1.0 4.0.8 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.2 All 96 releases
makecommerce / makecommerce / admin / dashboard.php

dashboard.php in MakeCommerce for WooCommerce 4.1.0, at makecommerce/admin/dashboard.php

521 lines 20.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace MakeCommerce\Admin;
4
5 // Ensure the Composer autoloader is included
6 require_once plugin_dir_path(__FILE__) . '../vendor-prefixed/autoload.php';
7
8 use MakeCommercePrefix\MakeCommerceShipping\SDK\Http\MakeCommerceClient;
9 use MakeCommercePrefix\Twig\Environment;
10 use MakeCommercePrefix\Twig\Loader\FilesystemLoader;
11 use MakeCommercePrefix\Twig\TwigFunction;
12
13 class Dashboard
14 {
15 public const DASHBOARD_SLUG = 'makecommerce_dashboard';
16 public const PAYMENTS_ONLY_SLUG = 'makecommerce_payments_only';
17 public const CONF_SLUG = 'makecommerce_configure';
18
19 public const SETTINGS_CAPABILITY = 'manage_options';
20
21 public const NONCE_ACTION = 'mc_save_settings';
22 public const NONCE_FIELD = 'mc_settings_nonce';
23
24 private string $api_mode;
25 private string $shop_id;
26 private string $secret_key;
27 private string $public_key;
28 private string $test_shop_id;
29 private string $test_secret_key;
30 private string $test_public_key;
31
32 private string $instance_id;
33 private string $shipping;
34 private string $payments;
35
36 public function initialize(): void
37 {
38 // Live
39 $this->shop_id = get_option('mc_shop_id', '');
40 $this->secret_key = get_option('mc_secret_key', '');
41 $this->public_key = get_option('mc_public_key', '');
42
43 // Test
44 $this->test_shop_id = get_option('mc_test_shop_id', '');
45 $this->test_secret_key = get_option('mc_test_secret_key', '');
46 $this->test_public_key = get_option('mc_test_public_key', '');
47
48 $this->api_mode = get_option('mc_api_mode', 'live');
49 $this->instance_id = get_option('mc_instance_id', '');
50 $this->shipping = get_option('mc_shipping', 'off');
51 $this->payments = get_option('mc_payments', 'off');
52 }
53
54
55 /**
56 * Add MakeCommerce menu to WordPress
57 * @return void
58 */
59 public function add_menu()
60 {
61 $icon = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDYiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0NiA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQyLjEyMzUgNDBDNDEuMDA2NiA0MCAzOS45NDI5IDM5LjQxMjYgMzkuMjUxNSAzOC41MDQ4TDI4LjYxNDMgMjIuNTM4N0MyOC42MTQzIDIyLjQ4NTMgMjguNjE0MyAyMi40ODUzIDI4LjYxNDMgMjIuNDMxOUwzOC40NTM3IDEyLjU1MzFDMzkuODM2NSAxMS4xNjQ4IDQxLjk2MzkgMTEuMTY0OCA0My4yNDA0IDEyLjU1MzFDNDQuNjIzMiAxMy45NDE1IDQ0LjYyMzIgMTYuMDc3NSA0My4yNDA0IDE3LjM1OUwzNy4yODM2IDIzLjM5MzFDMzcuMjgzNiAyMy4zOTMxIDM3LjIzMDQgMjMuNDQ2NCAzNy4yODM2IDIzLjQ5OThMNDQuNzgyOCAzNC44NzM3QzQ1Ljc5MzMgMzYuNDc1NyA0NS4zNjc4IDM4LjUwNDggNDMuODc4NiAzOS42Nzk2QzQzLjUwNjMgMzkuNzg2NCA0Mi44MTQ5IDQwIDQyLjEyMzUgNDBaTTIzLjkzMzkgNDBDMjIuMDE5MiA0MCAyMC41MyAzOC41MDQ4IDIwLjUzIDM2LjU4MjVWMy42ODg5OUMyMC41MyAxLjcxMzI0IDIyLjE3ODggLTAuMTAyMzA5IDI0LjE0NjcgMC4wMDQ0ODgzOUMyNi4wMDgyIDAuMTExMjg1IDI3LjM5MSAxLjU1MzA1IDI3LjM5MSAzLjQyMlYzNi41ODI1QzI3LjMzNzggMzguNTA0OCAyNS44NDg2IDQwIDIzLjkzMzkgNDBaTTEzLjY2OSA0MEMxMS43NTQzIDQwIDEwLjI2NTEgMzguNTA0OCAxMC4yNjUxIDM2LjU4MjVWMTUuMTY5N0MxMC4yNjUxIDEzLjE5MzkgMTEuOTEzOSAxMS4zNzg0IDEzLjg4MTggMTEuNDg1MkMxNS43NDMzIDExLjU5MiAxNy4xMjYxIDEzLjAzMzcgMTcuMTI2MSAxNC45MDI3VjM2LjYzNTlDMTcuMDcyOSAzOC41MDQ4IDE1LjU4MzcgNDAgMTMuNjY5IDQwWk0zLjQwNDE0IDQwQzEuNDg5NDUgNDAgMC4wMDAyNDQxNDEgMzguNTA0OCAwLjAwMDI0NDE0MSAzNi41ODI1VjI2LjU5N0MwLjAwMDI0NDE0MSAyNC42MjEyIDEuNjQ5MDEgMjIuODA1NyAzLjYxNjg5IDIyLjkxMjVDNS40NzgzOSAyMy4wMTkzIDYuODYxMjMgMjQuNDYxIDYuODYxMjMgMjYuMzNWMzYuNjM1OUM2LjgwODA0IDM4LjUwNDggNS4zNzIwMiA0MCAzLjQwNDE0IDQwWiIgZmlsbD0iIzMyQ0I2NCIvPgo8L3N2Zz4K';
62 if (!self::check_store_setup()) {
63 add_menu_page(
64 'MakeCommerce',
65 'MakeCommerce',
66 'manage_options',
67 self::DASHBOARD_SLUG,
68 [$this, 'render_setup_wizard'],
69 $icon,
70 58
71 );
72
73 return;
74 }
75
76 add_menu_page(
77 'MakeCommerce',
78 'MakeCommerce',
79 'manage_options',
80 self::DASHBOARD_SLUG,
81 [$this, 'render_shipping_configuration_iframe'],
82 $icon,
83 58
84 );
85
86 add_submenu_page(
87 '_empty_parent',
88 'MakeCommerce Configure',
89 'MakeCommerce Configure',
90 'manage_options',
91 self::CONF_SLUG,
92 [$this, 'render_plugin_configure_page']
93 );
94
95 if ($this->only_payments_configured()){
96 add_submenu_page(
97 '_empty_parent',
98 'MakeCommerce Payments',
99 'MakeCommerce Payments',
100 'manage_options',
101 self::PAYMENTS_ONLY_SLUG,
102 [$this, 'render_payments_only_page']
103 );
104 }
105 }
106
107 /**
108 * Remove the parent menu's submenu
109 * @return void
110 */
111 public function remove_parent_menu(): void
112 {
113 remove_submenu_page('makecommerce_dashboard', 'makecommerce_dashboard');
114 }
115
116
117 /**
118 * MC Payment method needs enabled field, so keep in sync with mc_payments setting
119 * @return void
120 */
121 public function sync_enabled_with_mc_payments($old_value, $new_value)
122 {
123 $option_key = 'woocommerce_' . MAKECOMMERCE_PLUGIN_ID . '_settings';
124
125 $settings = get_option($option_key, []);
126
127 if (!is_array($settings)) {
128 $settings = [];
129 }
130
131 $settings['enabled'] = ($new_value === 'on') ? 'yes' : 'no';
132
133 update_option($option_key, $settings);
134 }
135
136 public function render_setup_wizard()
137 {
138 if ($this->payments !== 'on' && $this->shipping !== 'on') {
139 $this->render_template('productSelection.twig', [
140 'shipping' => $this->shipping,
141 'payments' => $this->payments,
142 'setupSelection' => true,
143 'newInstall' => $this->is_new_install()
144 ]);
145 } else if ($this->checkApiCredentials()){
146 // if user has prefilled credentials, then render iframe
147 $this->render_shipping_configuration_iframe();
148 } else {
149 $this->render_template('credentials.twig');
150 }
151 }
152
153 function render_plugin_configure_page()
154 {
155 $this->render_template('productSelection.twig', [
156 'shipping' => $this->shipping,
157 'payments' => $this->payments,
158 'newInstall' => $this->is_new_install()
159 ]);
160 }
161
162 function render_payments_only_page()
163 {
164 $this->render_template('credentialsPopup.twig', ['render_footer' => false]);
165 $this->render_template('onlyPayments.twig', [
166 'configure_url' => admin_url('admin.php?page=' . self::CONF_SLUG)
167 ]);
168 }
169
170 private function render_template(string $template, array $data = []): void
171 {
172 $loader = new FilesystemLoader(plugin_dir_path(__FILE__) . 'templates');
173 $twig = new Environment($loader);
174
175 $twig->addFunction(new TwigFunction('__', function (string $text, string $domain = 'wc_makecommerce_domain') {
176 return __($text, $domain);
177 }));
178
179 $baseData = [
180 'path' => plugin_dir_url(__DIR__),
181 's3_path' => \MakeCommerce::get_static_url(),
182 'shopId' => $this->shop_id,
183 'secretKey' => $this->secret_key,
184 'publicKey' => $this->public_key,
185 'testShopId' => $this->test_shop_id,
186 'testSecretKey' => $this->test_secret_key,
187 'testPublicKey' => $this->test_public_key,
188 'apiMode' => $this->api_mode,
189 'instanceId' => $this->instance_id,
190 'shopException' => get_option('mc_credentials_error'),
191 'nonceField' => self::NONCE_FIELD,
192 'nonce' => wp_create_nonce(self::NONCE_ACTION),
193 ];
194
195 echo $twig->render($template, array_merge($baseData, $data));
196 }
197
198 public function render_shipping_configuration_iframe()
199 {
200 if (!$this->checkApiCredentials()){
201 $this->render_template('credentials.twig');
202 return;
203 }
204
205 $shipping = get_option('mc_shipping', 'off');
206 $payments = get_option('mc_payments', 'off');
207
208 if ($shipping !== 'off') {
209 try {
210 $client = $this->get_client();
211
212 $token = $client->connectShop(
213 userAgent: $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
214 remoteAddr: get_site_url() ?? $_SERVER['REMOTE_ADDR'],
215 orderUrl: admin_url( 'post.php?post={id}&action=edit' ),
216 webhookUrl: home_url('/')
217 );
218
219 if (empty($token->body->jwt)) {
220 throw new \Exception('JWT token is missing in the response.');
221 }
222
223 $url = $client->getIframeUrl($token->body->jwt);
224
225 if (empty($url)) {
226 throw new \Exception('Iframe URL could not be generated.');
227 }
228
229 echo '<iframe id="mcIframe" src="' . esc_url($url) . '" width="100%"></iframe>';
230
231 // Add postMessage if label print was requested
232 if (isset($_GET['mc_print_label']) && isset($_GET['mc_shipment_id'])) {
233 $label_data = json_encode([
234 'type' => 'print_label',
235 'mc_shipment_id' => sanitize_text_field($_GET['mc_shipment_id'])
236 ]);
237 echo '<script> let labelPrinted = false; document.getElementById("mcIframe").addEventListener("load", function() {
238 if (labelPrinted) return; labelPrinted = true; this.contentWindow.postMessage( '.$label_data.', "*")});</script>';
239 }
240
241 $this->render_template('credentialsPopup.twig', ['render_footer' => false]);
242 } catch (\Throwable $e) {
243 if ( function_exists( 'wc_get_logger' ) ) {
244 $logger = wc_get_logger();
245 $log_context = [ 'source' => 'makecommerce-errors' ];
246 $logger->error('Error loading iframe: ' . json_encode($e->getMessage()), $log_context);
247 }
248 // Problem with getting iframe
249 $this->render_template('error.twig', ['mc_error' => __('Failed to load Iframe. Please try again later.', 'wc_makecommerce_domain')]);
250 }
251 } else if ($payments !== 'off'){
252 wp_redirect(admin_url('admin.php?page=' . self::PAYMENTS_ONLY_SLUG));
253 } else {
254 wp_redirect(admin_url('admin.php?page=' . self::CONF_SLUG));
255 }
256 }
257
258 public function save_settings(): void {
259 $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
260
261 // if not our page
262 if (
263 $current_page !== self::DASHBOARD_SLUG &&
264 $current_page !== self::CONF_SLUG &&
265 $current_page !== self::PAYMENTS_ONLY_SLUG
266 ) {
267 return;
268 }
269
270 if (!$this->is_settings_submission()) {
271 return;
272 }
273
274 if (!current_user_can(self::SETTINGS_CAPABILITY)) {
275 wp_die(
276 esc_html__('You do not have permission to change MakeCommerce settings.', 'wc_makecommerce_domain'),
277 esc_html__('Forbidden', 'wc_makecommerce_domain'),
278 ['response' => 403]
279 );
280 }
281
282 check_admin_referer(self::NONCE_ACTION, self::NONCE_FIELD);
283
284 // Switch back to old module
285 if(isset($_POST['switch']) && $_POST['switch'] === 'switch_to_old') {
286 $this->switch_to_old_plugin();
287 }
288
289 // Save settings on setup selection
290 if (isset($_POST['setup_selection']) && $_POST['setup_selection'] === 'mc_product'){
291 $this->save_product_selection_settings(true);
292 }
293
294 // Save settings on product selection
295 if (isset($_POST['product_selection']) && $_POST['product_selection'] === 'mc_product'){
296 $this->save_product_selection_settings();
297 }
298
299 // Save credentials
300 if (isset($_POST['save_credentials']) && $_POST['save_credentials'] === 'mc_credentials'){
301 $this->save_credentials_settings();
302 }
303 }
304
305 /**
306 * Whether this request submits one of our settings forms.
307 *
308 * @return bool
309 */
310 private function is_settings_submission(): bool
311 {
312 if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
313 return false;
314 }
315
316 return isset($_POST['switch'])
317 || isset($_POST['setup_selection'])
318 || isset($_POST['product_selection'])
319 || isset($_POST['save_credentials']);
320 }
321
322 private function switch_to_old_plugin(){
323 update_option('mc_shipping_plus', 'no');
324 $this->mc_creds_migration();
325 wp_redirect(admin_url('admin.php?page=wc-settings&tab=advanced&section=mk_api'));
326 exit;
327 }
328
329 /**
330 * Run credentials migration when 'mc_shipping_plus' is turned off
331 * This is run to have compatible credentials on the old module as well
332 * @return void
333 */
334 private function mc_creds_migration(): void
335 {
336 $migration_map = [
337 'mc_shop_id' => 'mk_shop_id',
338 'mc_secret_key' => 'mk_private_key',
339 'mc_public_key' => 'mk_public_key',
340 'mc_test_shop_id' => 'mk_test_shop_id',
341 'mc_test_secret_key' => 'mk_test_private_key',
342 'mc_test_public_key' => 'mk_test_public_key',
343 'mc_api_mode' => 'mk_api_type',
344 ];
345
346 foreach ($migration_map as $new_key => $old_key) {
347 $new_value = get_option($new_key, null);
348
349 if ($new_value !== null && $new_value !== '') {
350 // set old plugins credentials to new plugins ones
351 update_option($old_key, $new_value);
352 }
353 }
354 }
355
356 private function save_product_selection_settings($setupSelection = false){
357 $this->payments = isset($_POST['payments']) ? 'on' : 'off';
358 $this->shipping = isset($_POST['shipping']) ? 'on' : 'off';
359
360 update_option('mc_payments', $this->payments);
361 update_option('mc_shipping', $this->shipping);
362
363 if(!$setupSelection){
364 if ($this->payments !== 'off' && $this->shipping !== 'off') {
365 wp_redirect(admin_url('admin.php?page=' . self::DASHBOARD_SLUG));
366 } elseif ($this->payments !== 'off') {
367 wp_redirect(admin_url('admin.php?page=' . self::PAYMENTS_ONLY_SLUG));
368 } else {
369 wp_redirect(admin_url('admin.php?page=' . self::DASHBOARD_SLUG));
370 }
371 }
372 }
373
374 private function save_credentials_settings(): void
375 {
376 $api_mode = ($_POST['mc_api_mode'] ?? '') === 'test' ? 'test' : 'live';
377 update_option('mc_api_mode', $api_mode);
378 $this->api_mode = $api_mode;
379
380 $shop_id = trim(wp_unslash($_POST['shopId'] ?? ''));
381 $secret_key = trim(wp_unslash($_POST['secretKey'] ?? ''));
382 $public_key = trim(wp_unslash($_POST['publicKey'] ?? ''));
383
384 $prefix = $api_mode === 'test' ? 'mc_test_' : 'mc_';
385
386 update_option($prefix . 'shop_id', $shop_id);
387 update_option($prefix . 'secret_key', $secret_key);
388 update_option($prefix . 'public_key', $public_key);
389
390 if ($api_mode === 'test') {
391 $this->test_shop_id = $shop_id;
392 $this->test_secret_key = $secret_key;
393 $this->test_public_key = $public_key;
394 } else {
395 $this->shop_id = $shop_id;
396 $this->secret_key = $secret_key;
397 $this->public_key = $public_key;
398 }
399
400 if($this->checkApiCredentials()){
401 // When credentials correctly submitted, update banklinks
402 \MakeCommerce\Payment::update_banklinks();
403 }
404 wp_redirect(admin_url('admin.php?page=' . self::DASHBOARD_SLUG));
405 exit;
406 }
407
408 private function get_client(): MakeCommerceClient
409 {
410 $instance_id = $this->instance_id ?? get_option('mc_instance_id', '');
411
412 if (empty($instance_id)) {
413 $instance_id = uniqid('', true);
414 update_option('mc_instance_id', $instance_id);
415 }
416 $this->instance_id = $instance_id;
417 $client_conf = \MakeCommerce::get_sdk_config();
418
419 $client = new MakeCommerceClient(
420 $this->api_mode,
421 $this->api_mode === 'test' ? $this->test_shop_id : $this->shop_id,
422 $this->api_mode === 'test' ? $this->test_secret_key : $this->secret_key,
423 $instance_id,
424 $client_conf
425 );
426
427 $shortLocale = substr(get_user_locale() ?: get_locale(), 0, 2);
428
429 if (in_array($shortLocale, ['et', 'en', 'lv', 'lt'], true)) {
430 $client->setLocale($shortLocale);
431 }
432
433 return $client;
434 }
435
436 public function enqueue_dashboard_scripts($hook)
437 {
438 if ($hook === 'toplevel_page_makecommerce_dashboard' || $hook === 'admin_page_makecommerce_payments_only') {
439 wp_enqueue_style('makecommerce-iframe-style', \MakeCommerce::get_static_url() . "modules/woocommerce/css/iframe.css");
440 wp_enqueue_script('bootstrap-bundle', plugin_dir_url(__DIR__) . 'assets/bootstrap.bundle.min.js', [], '5.3.3', true);
441 wp_enqueue_script('mc-shop-credentials', \MakeCommerce::get_static_url() . "modules/woocommerce/js/mc-shop-credentials.js", ['bootstrap-bundle'], null, true);
442 wp_enqueue_script('mc-module-config', plugin_dir_url(__FILE__) . 'js/mc-module-config.js', ['bootstrap-bundle'], null, true);
443 wp_enqueue_script('mc-iframe-height', plugin_dir_url(__FILE__) . 'js/mc-iframe-height.js', [], null, true);
444 // Pass redirect url to javascript
445 wp_localize_script('mc-module-config', 'mcApiData', ['redirect_url' => admin_url('admin.php?page=' . self::CONF_SLUG)]);
446 }
447
448 wp_enqueue_script('mc-api-toggle', plugin_dir_url(__FILE__) . 'js/mc-api-toggle.js', ['jquery'], null, true);
449 }
450
451 public function hide_admin_notices()
452 {
453 $screen = get_current_screen();
454 if ($screen && in_array($screen->id, ['toplevel_page_makecommerce_dashboard', 'makecommerce_page_makecommerce',
455 'admin_page_' . self::CONF_SLUG, 'admin_page_' . self::PAYMENTS_ONLY_SLUG])) {
456 remove_all_actions('admin_notices');
457 remove_all_actions('all_admin_notices');
458 }
459 }
460
461 private function only_payments_configured(): bool {
462 $shipping = get_option( 'mc_shipping', 'off' );
463 $payments = get_option( 'mc_payments', 'off' );
464 return $shipping !== 'on' && $payments === 'on';
465 }
466
467 public static function check_store_setup(): bool
468 {
469 $mode = get_option( 'mc_api_mode', 'live' );
470
471 $shipping = get_option( 'mc_shipping', 'off' );
472 $payments = get_option( 'mc_payments', 'off' );
473
474 $shop_id = get_option( $mode === 'test' ? 'mc_test_shop_id' : 'mc_shop_id' );
475 $public_key = get_option( $mode === 'test' ? 'mc_test_public_key' : 'mc_public_key' );
476 $secret_key = get_option( $mode === 'test' ? 'mc_test_secret_key' : 'mc_secret_key' );
477
478 $mc_credentials_error = get_option('mc_credentials_error', '');
479
480 // Problem with credentials
481 if (!empty($mc_credentials_error)) {
482 return false;
483 }
484
485 return ( $shipping === 'on' || $payments === 'on' )
486 && ( $shop_id && $public_key && $secret_key );
487 }
488
489 private function is_new_install() {
490 return get_option('makecommerce_install_status', 'upgrade') === 'new_install';
491 }
492
493 private function checkApiCredentials(): bool
494 {
495 try {
496 $client = $this->get_client();
497 $client->connectShop(
498 userAgent: $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
499 remoteAddr: get_site_url() ?? $_SERVER['REMOTE_ADDR'],
500 orderUrl: admin_url( 'post.php?post={id}&action=edit' ),
501 webhookUrl: home_url('/')
502 );
503 update_option('mc_credentials_error', '');
504 return true;
505 } catch (\Throwable $e) {
506 $label = $this->api_mode === 'test' ? __('Sandbox', 'wc_makecommerce_domain') : __('Live', 'wc_makecommerce_domain');
507 if ( function_exists( 'wc_get_logger' ) ) {
508 $logger = wc_get_logger();
509 $log_context = [ 'source' => 'makecommerce-errors' ];
510 $logger->error('Unable to verify credentials: ' . json_encode($e->getMessage()), $log_context);
511 }
512 update_option('mc_credentials_error',
513 sprintf(
514 /* translators: %s: Environment name */
515 __('Unable to verify %s credentials', 'wc_makecommerce_domain'), $label)
516 );
517 return false;
518 }
519 }
520 }
521