PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.1.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.1.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
better-payment / includes / Admin / ReactAdmin.php

ReactAdmin.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.1.1, at includes/Admin/ReactAdmin.php

402 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\Admin;
4
5 use Better_Payment\Lite\Controller;
6 use Better_Payment\Lite\Admin\DB;
7 use Better_Payment\Lite\Traits\Helper as TraitsHelper;
8
9 /**
10 * Exit if accessed directly
11 */
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 /**
17 * React Admin handler class
18 *
19 * @since 1.5.0
20 */
21 class ReactAdmin extends Controller
22 {
23 use TraitsHelper;
24
25 protected $pro_enabled;
26 protected $page_slug_prefix;
27 protected $file_version;
28
29 /**
30 * Constructor
31 *
32 * @since 1.5.0
33 */
34 public function __construct($page_slug_prefix = 'better-payment')
35 {
36 $this->page_slug_prefix = $page_slug_prefix;
37 $this->file_version = defined('WP_DEBUG') && WP_DEBUG ? time() : BETTER_PAYMENT_VERSION;
38 $this->pro_enabled = apply_filters('better_payment/pro_enabled', false);
39
40 add_action('init', [$this, 'handle_old_page_redirect']);
41 add_action('admin_menu', [$this, 'register_menu']);
42 add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
43 add_action('admin_enqueue_scripts', [$this, 'customize_admin_footer']);
44
45 //EL Editor Style
46 add_action('elementor/editor/before_enqueue_scripts', [$this, 'editor_enqueue_scripts']);
47 }
48
49 /**
50 * Handle old page redirect
51 *
52 * @since 2.0.0
53 */
54 public function handle_old_page_redirect()
55 {
56 if (isset($_GET['page']) && trim(sanitize_text_field($_GET['page'])) === 'better-payment-settings') {
57 wp_safe_redirect(admin_url('admin.php?page=' . $this->page_slug_prefix . '-admin&tab=dashboard'));
58 exit;
59 }
60 }
61
62 /**
63 * Enqueue editor scripts
64 *
65 * @since 0.0.1
66 */
67 public function editor_enqueue_scripts()
68 {
69 // bp icon font
70 wp_enqueue_style(
71 'bp-icon-admin-editor',
72 BETTER_PAYMENT_ASSETS . '/icon/style.min.css',
73 false
74 );
75 }
76
77 /**
78 * Register admin menu for React SPA
79 *
80 * @since 1.5.0
81 */
82 public function register_menu()
83 {
84 add_menu_page(
85 __('Better Payment', 'better-payment'),
86 __('Better Payment', 'better-payment'),
87 'manage_options',
88 $this->page_slug_prefix . '-admin',
89 [$this, 'render_react_admin_page'],
90 BETTER_PAYMENT_ASSETS . '/img/better-payment-icon-white-small.png',
91 64
92 );
93
94 $submenu_page_list = apply_filters('better_payment/admin/get_submenu_page_list', array(
95 $this->page_slug_prefix . '-admin&tab=dashboard' => array(
96 'title' => __('Dashboard', 'better-payment'),
97 'capability' => 'manage_options',
98 'callback' => [$this, 'render_react_admin_page'],
99 ),
100 $this->page_slug_prefix . '-admin&tab=transactions' => array(
101 'title' => __('Transactions', 'better-payment'),
102 'capability' => 'manage_options',
103 'callback' => [$this, 'render_react_admin_page'],
104 ),
105 $this->page_slug_prefix . '-admin&tab=analytics' => array(
106 'title' => __('Analytics', 'better-payment'),
107 'capability' => 'manage_options',
108 'callback' => [$this, 'render_react_admin_page'],
109 ),
110 $this->page_slug_prefix . '-admin&tab=settings' => array(
111 'title' => __('Settings', 'better-payment'),
112 'capability' => 'manage_options',
113 'callback' => [$this, 'render_react_admin_page'],
114 ),
115 ), $this->page_slug_prefix );
116
117 foreach( $submenu_page_list as $slug => $setting ) {
118 add_submenu_page(
119 $this->page_slug_prefix . '-admin',
120 $setting['title'],
121 $setting['title'],
122 $setting['capability'],
123 $slug,
124 $setting['callback']
125 );
126 }
127
128 remove_submenu_page($this->page_slug_prefix . '-admin', $this->page_slug_prefix . '-admin');
129 }
130
131 /**
132 * Render the React admin page
133 *
134 * @since 1.5.0
135 */
136 public function render_react_admin_page()
137 {
138 $initial_data = $this->get_initial_admin_data();
139
140 add_filter('admin_body_class', function($classes) {
141 return $classes . ' better-payment-admin-page';
142 });
143
144 remove_all_actions('admin_notices');
145 remove_all_actions('all_admin_notices');
146
147 ?>
148 <div class="wrap">
149 <div id="better-payment-admin-root">
150 <!-- <div class="bp-loading-placeholder">
151 <div class="bp-loading-spinner"></div>
152 <p><?php //_e('Loading Better Payment Admin...', 'better-payment'); ?></p>
153 </div> -->
154 </div>
155 </div>
156
157 <script type="text/javascript">
158 window.betterPaymentAdmin = <?php echo wp_json_encode($initial_data); ?>;
159 </script>
160
161 <style>
162 .bp-loading-placeholder {
163 display: flex;
164 flex-direction: column;
165 align-items: center;
166 justify-content: center;
167 min-height: 400px;
168 gap: 16px;
169 color: #646970;
170 }
171
172 .bp-loading-spinner {
173 width: 32px;
174 height: 32px;
175 border: 3px solid #f3f3f3;
176 border-top: 3px solid #0073aa;
177 border-radius: 50%;
178 animation: bp-spin 1s linear infinite;
179 }
180
181 @keyframes bp-spin {
182 0% { transform: rotate(0deg); }
183 100% { transform: rotate(360deg); }
184 }
185
186 .better-payment-admin {
187 background: #f0f0f1;
188 min-height: calc(100vh - 32px);
189 margin: -20px -20px -20px -2px;
190 padding: 0;
191 }
192
193 .wrap .better-payment-admin {
194 margin: -20px -20px -20px -2px;
195 }
196
197 .better-payment-admin-page .notice,
198 .better-payment-admin-page .error,
199 .better-payment-admin-page .updated {
200 display: none !important;
201 }
202
203 .better-payment-admin-page #adminmenumain {
204 display: block !important;
205 }
206
207 .better-payment-admin-page #wpadminbar {
208 display: block !important;
209 }
210
211 .better-payment-admin-page #wpfooter {
212 display: block !important;
213 }
214
215 @media (max-width: 960px) {
216 .folded .better-payment-admin {
217 margin-left: -2px;
218 }
219 }
220
221 @media (max-width: 782px) {
222 .auto-fold .better-payment-admin {
223 margin-left: -2px;
224 }
225 }
226
227 @media print {
228 body {
229 transform: scale(1);
230 background: white !important;
231 }
232
233 body, body *, .wpcontent {
234 visibility: hidden !important;
235 }
236
237 .bp-invoice-body,
238 .bp-invoice-body * {
239 visibility: visible !important;
240 }
241
242 /* Make modal fill the full page */
243 .bp-invoice-body {
244 position: absolute !important;
245 left: 0;
246 top: 100;
247 width: 100% !important;
248 height: auto !important;
249 }
250
251 .bp-button-wrapper {
252 display: none !important;
253 }
254 }
255 </style>
256 <?php
257 }
258
259 /**
260 * Get initial data for React admin app
261 *
262 * @since 1.5.0
263 * @return array Initial data
264 */
265 private function get_initial_admin_data()
266 {
267 $settings = DB::get_settings();
268
269 return [
270 'apiUrl' => rest_url('better-payment/v1/'),
271 'ajaxUrl' => admin_url('admin-ajax.php'),
272 'nonce' => wp_create_nonce('wp_rest'),
273 'importNonce' => wp_create_nonce('better_payment_transaction_import_nonce'),
274 'logoUrl' => BETTER_PAYMENT_ASSETS . '/img/better-payment-icon-white-small.png',
275 'adminUrl' => admin_url('admin.php?page=' . $this->page_slug_prefix . '-admin'),
276 'adminPostUrl' => admin_url('admin-post.php'),
277 'settings' => $settings,
278 'proEnabled' => $this->pro_enabled,
279 'currentUser' => [
280 'id' => get_current_user_id(),
281 'name' => wp_get_current_user()->display_name,
282 'email' => wp_get_current_user()->user_email
283 ],
284 'currencies' => $this->get_currency_list(),
285 'currencySymbol' => $this->get_currency_symbol( $settings['better_payment_settings_general_general_currency'] ),
286 ];
287 }
288
289 /**
290 * Customize admin footer text and version display
291 *
292 * @since 1.5.0
293 */
294 public function customize_admin_footer($hook)
295 {
296 // Only apply to Better Payment admin pages
297 if (strpos($hook, $this->page_slug_prefix . '-admin') === false) {
298 return;
299 }
300
301 add_filter('admin_footer_text', [$this, 'get_footer_text']);
302 add_filter('update_footer', [$this, 'get_footer_version']);
303 }
304
305 /**
306 * Get custom footer text
307 *
308 * @since 1.5.0
309 * @return string
310 */
311 public function get_footer_text()
312 {
313 return __('Thank you for using <a href="https://betterpayment.co/" target="_blank">Better Payment</a>', 'better-payment');
314 }
315
316 /**
317 * Get footer version text
318 *
319 * @since 1.5.0
320 * @return string
321 */
322 public function get_footer_version()
323 {
324 $free_version = BETTER_PAYMENT_VERSION;
325
326 // Check if Pro version is installed and active
327 if ($this->pro_enabled && defined('BETTER_PAYMENT_PRO_VERSION')) {
328 $pro_version = BETTER_PAYMENT_PRO_VERSION;
329 return sprintf(
330 __('<span class="bp-footer-version-divider">Free Version <span class="bp-footer-version">%s</span></span> <span>Pro Version <span class="bp-footer-version">%s</span></span>', 'better-payment'),
331 $free_version,
332 $pro_version
333 );
334 }
335
336 return sprintf(
337 __('<span class="bp-free-version"><span>Free Version</span> <span class="bp-footer-version">%s</span> </span>', 'better-payment'),
338 $free_version
339 );
340 }
341
342 /**
343 * Enqueue admin assets for React app
344 *
345 * @since 1.5.0
346 */
347 public function enqueue_admin_assets($hook)
348 {
349 if (strpos($hook, $this->page_slug_prefix . '-admin') === false) {
350 return;
351 }
352
353 wp_enqueue_script('wp-element');
354 wp_enqueue_script('wp-api-fetch');
355 wp_enqueue_script('wp-components');
356 wp_enqueue_script('wp-i18n');
357
358 wp_enqueue_script('wp-element');
359 wp_enqueue_script('wp-hooks');
360 wp_enqueue_script('wp-i18n');
361 wp_enqueue_script('wp-api-fetch');
362 wp_enqueue_script('react');
363 wp_enqueue_script('react-dom');
364
365 $admin_js_file = BETTER_PAYMENT_ASSETS . '/admin/admin.min.js';
366 $admin_css_file = BETTER_PAYMENT_ASSETS . '/admin/admin.min.css';
367
368 if (!file_exists(BETTER_PAYMENT_PATH . '/assets/admin/admin.min.js')) {
369 $admin_js_file = BETTER_PAYMENT_ASSETS . '/admin/admin.js';
370 }
371
372 if (!file_exists(BETTER_PAYMENT_PATH . '/assets/admin/admin.min.css')) {
373 $admin_css_file = BETTER_PAYMENT_ASSETS . '/admin/admin.css';
374 }
375
376 wp_enqueue_script(
377 'better-payment-react-admin',
378 $admin_js_file,
379 ['wp-element', 'wp-hooks', 'wp-i18n', 'wp-api-fetch', 'react', 'react-dom'],
380 $this->file_version,
381 true
382 );
383
384 wp_enqueue_style(
385 'better-payment-react-admin',
386 $admin_css_file,
387 [],
388 $this->file_version
389 );
390
391 wp_add_inline_script(
392 'better-payment-react-admin',
393 'wp.apiFetch.use(wp.apiFetch.createNonceMiddleware("' . wp_create_nonce('wp_rest') . '"));',
394 'before'
395 );
396 $page_slug = $this->page_slug_prefix . '-admin';
397 $admin_base_url = admin_url('admin.php?page=' . $this->page_slug_prefix . '-admin');
398 $inline_spa_nav = "(function(){\n\n var PAGE_SLUG = '" . esc_js($page_slug) . "';\n var BASE_URL = '" . esc_url($admin_base_url) . "';\n\n function getTabFromUrl(){\n var params = new URLSearchParams(window.location.search);\n return params.get('tab') || 'dashboard';\n }\n\n function buildUrl(tab){\n var url = new URL(BASE_URL, window.location.origin);\n url.searchParams.set('tab', tab);\n return url.toString();\n }\n\n function setActiveSubmenu(tab){\n try {\n var top = document.getElementById('toplevel_page_'+PAGE_SLUG);\n if(!top) return;\n var submenu = top.querySelector('.wp-submenu');\n if(!submenu) return;\n // remove current from all\n submenu.querySelectorAll('li').forEach(function(li){ li.classList.remove('current'); });\n // match link by tab param\n var target = Array.prototype.find.call(submenu.querySelectorAll('a'), function(a){ return a.href && a.href.indexOf('page='+PAGE_SLUG) !== -1 && a.href.indexOf('tab='+tab) !== -1; });\n if(target && target.parentElement){ target.parentElement.classList.add('current'); }\n // ensure top-level marked as current submenu\n top.classList.add('wp-has-current-submenu');\n top.classList.add('current');\n } catch(e){}\n }\n\n // Global navigate helper used by WP menu interceptors and can be used by React too\n window.betterPaymentNavigate = function(tab, method){\n if(!tab){ tab = 'dashboard'; }\n var m = method === 'replace' ? 'replaceState' : 'pushState';\n var url = buildUrl(tab);\n try { window.history[m]({}, '', url); } catch(e){}\n setActiveSubmenu(tab);\n window.dispatchEvent(new CustomEvent('bp:navigate', { detail: { tab: tab } }));\n };\n\n // Intercept WP submenu clicks under our menu only\n function clickHandler(e){\n var link = e.target.closest('#toplevel_page_'+PAGE_SLUG+' .wp-submenu a');\n if(!link) return;\n var href = link.getAttribute('href') || '';\n if(href.indexOf('page='+PAGE_SLUG) === -1) return;\n e.preventDefault();\n var url = new URL(href, window.location.origin);\n var tab = url.searchParams.get('tab') || 'dashboard';\n window.betterPaymentNavigate(tab, 'push');\n }\n document.addEventListener('click', clickHandler, true);\n\n // Reflect browser back/forward\n window.addEventListener('popstate', function(){ setActiveSubmenu(getTabFromUrl()); });\n\n // Reflect initial state on load\n document.addEventListener('DOMContentLoaded', function(){ setActiveSubmenu(getTabFromUrl()); });\n\n // Also respond to React-driven page changes (optional hook)\n window.addEventListener('bp:page-changed', function(e){ if(e && e.detail && e.detail.tab){ setActiveSubmenu(e.detail.tab); } });\n\n})();";
399 wp_add_inline_script('better-payment-react-admin', $inline_spa_nav, 'after');
400 }
401 }
402