PluginProbe
MyRewards / trunk
MyRewards vtrunk
5.7.8 5.7.7 5.7.6 trunk 1.2.2 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.1 2.2.0 2.3.0 2.4.0 2.4.1 2.5.0 2.6.4 2.6.6 3.0.0.0 3.1.0 3.1.2 3.1.2.1 3.10.4 3.10.9 All 165 releases
woorewards / include / ui / admin.php

admin.php in MyRewards trunk, at include/ui/admin.php

1,690 lines 73.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace LWS\WOOREWARDS\Ui;
4
5 // don't call the file directly
6 if (!defined('ABSPATH')) exit();
7
8 /** Create the backend menu and settings pages. */
9 class Admin
10 {
11 const NOTICE_NO_POOL = 'lws-wre-pool-nothing-loaded';
12
13 public function __construct()
14 {
15 // comes after the addon, let that part to it if any
16 \add_filter('lws_adminpanel_make_page_' . LWS_WOOREWARDS_PAGE . '.customers', array($this, 'addSponsorshipTab'), 2000);
17
18 /** @param array, the fields settings array. @param Pool */
19 \add_filter('lws_woorewards_admin_pool_general_settings', array($this, 'getPoolGeneralSettings'), 10, 2);
20
21 lws_register_pages($this->managePages());
22 \add_action('admin_enqueue_scripts', array($this, 'scripts'));
23
24 // replace usual notice by a badge teaser
25 if (!defined('LWS_WOOREWARDS_ACTIVATED') || !LWS_WOOREWARDS_ACTIVATED)
26 \add_filter('pre_set_transient_settings_errors', array($this, 'noticeSettingsSaved'));
27
28 $this->checkCouponsEnabled();
29 }
30
31 protected function getCurrentPage()
32 {
33 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- page routing only
34 if (isset($_REQUEST['page']) && ($current = \sanitize_text_field(\wp_unslash($_REQUEST['page']))))
35 return $current;
36 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- page routing only
37 if (isset($_REQUEST['option_page']) && ($current = \sanitize_text_field(\wp_unslash($_REQUEST['option_page']))))
38 return $current;
39 return false;
40 }
41
42 protected function checkCouponsEnabled()
43 {
44 if (defined('DOING_AJAX') && DOING_AJAX)
45 return;
46
47 if (function_exists('\wc_coupons_enabled') && !\wc_coupons_enabled() && !\get_option('lws_woorewards_ignore_woocommerce_disable_coupons')) {
48 $ignore = false;
49 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- admin notice dismissal
50 if (isset($_GET['lws_wr_wc_coupons_enable']) && in_array(\sanitize_text_field(\wp_unslash($_GET['lws_wr_wc_coupons_enable'])), array('yes', 'ignore'))) {
51 if (\current_user_can('manage_options')) {
52 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
53 if ( \sanitize_text_field( \wp_unslash( $_GET['lws_wr_wc_coupons_enable'] ) ) == 'yes' ) {
54 \update_option( 'woocommerce_enable_coupons', 'yes' );
55 \update_option( 'lws_woorewards_ignore_woocommerce_disable_coupons', '' );
56 } else {
57 \update_option( 'lws_woorewards_ignore_woocommerce_disable_coupons', 'yes' );
58 }
59 }
60 $ignore = true;
61 }
62
63 if (!$ignore) {
64 $message = array();
65 $message[] = __("WooCommerce Coupons are disabled. Several MyRewards features will be broken without Coupons.", 'woorewards-lite');
66 $message[] = __("You can check your WooCommerce General Settings and look for : <b>Enable coupons</b>.", 'woorewards-lite');
67 if (\current_user_can('manage_options')) {
68 $message[] = sprintf(
69 /* translators: %1$s: link to resolve, %2$s: link to ignore */
70 __( '%1$s or %2$s this warning at your own risks.', 'woorewards-lite' ),
71 sprintf(
72 "<a href='%s' class='button primary'>%s</a>",
73 \esc_attr( \add_query_arg( 'lws_wr_wc_coupons_enable', 'yes' ) ),
74 __( "Click here to resolve the problem immediately", 'woorewards-lite' )
75 ),
76 sprintf(
77 "<a href='%s' class=''>%s</a>",
78 \esc_attr( \add_query_arg( 'lws_wr_wc_coupons_enable', 'ignore' ) ),
79 __( "ignore", 'woorewards-lite' )
80 )
81 );
82 }
83 \lws_admin_add_notice_once('woocommerce_enable_coupons', implode('<br/>', $message), array('level' => 'error'));
84 }
85 }
86 }
87
88 public function scripts($hook)
89 {
90 // Force the menu icon with lws-icons font
91 \wp_enqueue_style('wr-menu-icon', LWS_WOOREWARDS_CSS . '/menu-icon.css', array(), LWS_WOOREWARDS_VERSION);
92
93 \wp_register_script('lws_wre_system_selector', LWS_WOOREWARDS_JS . '/poolsettings.js', array('lws-base64'), LWS_WOOREWARDS_VERSION, true);
94 \wp_register_style('lws_wre_system_selector', LWS_WOOREWARDS_CSS . '/poolsettings.css', array(), LWS_WOOREWARDS_VERSION);
95
96 if (false !== ($ppos = strpos($hook, LWS_WOOREWARDS_PAGE))) {
97 $page = substr($hook, $ppos);
98 $tab = isset($_GET['tab']) ? \sanitize_text_field(\wp_unslash($_GET['tab'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab routing
99
100 if (!defined('LWS_WOOREWARDS_ACTIVATED') || !LWS_WOOREWARDS_ACTIVATED) {
101 // let badge teaser replace the notice
102 \wp_enqueue_style('lws-wre-notice', LWS_WOOREWARDS_CSS . '/notice.css', array(), LWS_WOOREWARDS_VERSION);
103 }
104
105 if ($page == LWS_WOOREWARDS_PAGE || false !== strpos($page, 'customers')) {
106 // labels displayed in points history
107 $labels = array(
108 'hist' => __("Points History", 'woorewards-lite'),
109 'desc' => __("Description", 'woorewards-lite'),
110 'date' => __("Date", 'woorewards-lite'),
111 'points' => __("Points", 'woorewards-lite'),
112 'total' => __("Total", 'woorewards-lite'),
113 );
114 // enqueue editlist column folding script
115 foreach (($deps = array('jquery', 'lws-tools')) as $dep)
116 \wp_enqueue_script($dep);
117
118 \wp_register_script('lws-wre-userspoints', LWS_WOOREWARDS_JS . '/userspoints.js', $deps, LWS_WOOREWARDS_VERSION, true);
119 \wp_localize_script('lws-wre-userspoints', 'lws_wr_userspoints_labels', $labels);
120 \wp_enqueue_script('lws-wre-userspoints');
121 \wp_enqueue_style('lws-wre-userspoints', LWS_WOOREWARDS_CSS . '/userspoints.css', array(), LWS_WOOREWARDS_VERSION);
122
123 \do_action('lws_adminpanel_enqueue_lac_scripts', array('select'));
124 \do_action('lws_woorewards_ui_userspoints_enqueue_scripts', $hook, $tab);
125 } else if (false !== strpos($page, 'loyalty')) {
126 \do_action('lws_adminpanel_enqueue_lac_scripts', array('select'));
127 } else if (false !== strpos($page, 'appearance')) {
128 \wp_enqueue_style('lws_wr_pointsoncart_hard', LWS_WOOREWARDS_CSS . '/pointsoncart.css', array(), LWS_WOOREWARDS_VERSION);
129 }
130
131 \wp_enqueue_script('lws-wre-coupon-edit', LWS_WOOREWARDS_JS . '/couponedit.js', array('jquery'), LWS_WOOREWARDS_VERSION, true);
132 }
133 }
134
135 /** Push an achievement teaser instead our usual notice at setting save. */
136 public function noticeSettingsSaved($value)
137 {
138 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- WP settings API handles nonce
139 if (!empty($value) && isset($_POST['option_page']) && false !== strpos(\sanitize_text_field(\wp_unslash($_POST['option_page'])), LWS_WOOREWARDS_PAGE)) {
140 $val = \current($value);
141 if (isset($val['type']) && $val['type'] == 'updated' && isset($val['code']) && $val['code'] == 'settings_updated') {
142 $teasers = array(
143 __("Add fun and achievements for your customers with the <a>Pro Version</a>", 'woorewards-lite'),
144 __("Try the <a>Pro Version</a> for free for 30 days", 'woorewards-lite'),
145 __("The <a>Pro Version</a> adds Events and Levelling systems. Try <a>it</a>", 'woorewards-lite')
146 );
147 \LWS_WooRewards::achievement(array(
148 'title' => __("Your settings have been saved.", 'woorewards-lite'),
149 'message' => str_replace(
150 '<a>',
151 "<a href='https://plugins.longwatchstudio.com/product/woorewards/' target='_blank'>",
152 $teasers[wp_rand(0, count($teasers) - 1)]
153 )
154 ));
155 }
156 }
157 return $value;
158 }
159
160 protected function managePages()
161 {
162 $pages = array();
163 $pages['wr_resume'] = $this->getResumePage();
164 $pages['wr_customers'] = $this->getCustomerPage();
165 if (false === ($pages['wr_settings'] = \apply_filters('lws_woorewards_ui_settings_page_get', false))) {
166 $pages['wr_settings'] = $this->getSettingsPage();
167 }
168 if (defined('LWS_WIZARD_SUMMONER')) {
169 $pages['wr_wizard'] = $this->getWizardPage();
170 }
171 //$pages['wr_features'] = $this->getFeaturesPage();
172 $pages['wr_appearance'] = $this->getAppearancePage();
173 $pages['wr_system'] = $this->getSystemPage();
174
175 if (!\apply_filters('lws-ap-release-woorewards', ''))
176 $pages['wr_proversion'] = $this->getProVersionPage();
177
178 return $pages;
179 }
180
181 protected function getResumePage()
182 {
183 $resumePage = array(
184 'title' => __("MyRewards", 'woorewards-lite'),
185 'id' => LWS_WOOREWARDS_PAGE,
186 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
187 'dashicons' => '',
188 'index' => 57,
189 'resume' => true,
190 'tabs' => array(
191 'wr_customers' => array(
192 'title' => __("Customers", 'woorewards-lite'),
193 'id' => 'resume_customers',
194 )
195 )
196 );
197 return $resumePage;
198 }
199
200 protected function getCustomerPage()
201 {
202 require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/userspoints.php';
203 require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/userspointsbulkaction.php';
204 $editlist = \lws_editlist(
205 'userspoints',
206 'user_id',
207 new \LWS\WOOREWARDS\Ui\Editlists\UsersPoints(),
208 \LWS\Adminpanel\EditList\Modes::FIX,
209 \apply_filters('lws_woorewards_admin_userspoints_filters', array(
210 'user_search' => new \LWS\Adminpanel\EditList\FilterSimpleField('usersearch', __('Search...', 'woorewards-lite')),
211 'points_add' => new \LWS\WOOREWARDS\Ui\Editlists\UsersPointsBulkAction('points_add')
212 ))
213 );
214
215
216 $cusPage = array(
217 'title' => __("Customers", 'woorewards-lite'),
218 'id' => LWS_WOOREWARDS_PAGE . '.customers',
219 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
220 'color' => '#A8CE38',
221 'image' => LWS_WOOREWARDS_IMG . '/r-customers.png',
222 'description' => __("Use this page to manage your customers, see and edit their points and rewards", 'woorewards-lite'),
223 'tabs' => array(
224 'wr_customers' => array(
225 'title' => __("Customers", 'woorewards-lite'),
226 'id' => 'wr_customers',
227 'icon' => 'lws-icon-users-wm',
228 'groups' => array(
229 'customers_points' => array(
230 'title' => __("Points Management", 'woorewards-lite'),
231 'icon' => 'lws-icon-users',
232 'color' => '#00768b',
233 'text' => __("Here you can see and manage your customers reward points", 'woorewards-lite')
234 . "<br/>" . __("You can view the points <b>history</b> by clicking the points total in the table", 'woorewards-lite'),
235 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('customers')),
236 'editlist' => $editlist,
237 )
238 )
239 )
240 )
241 );
242 return $cusPage;
243 }
244
245 protected function getSettingsPage()
246 {
247 return array(
248 'title' => __("Settings", 'woorewards-lite'),
249 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
250 'id' => LWS_WOOREWARDS_PAGE . '.loyalty',
251 'color' => '#526981',
252 'image' => LWS_WOOREWARDS_IMG . '/r-loyalty-systems.png',
253 'description' => __("Use this page to manage your loyalty program, see and edit actions and rewards", 'woorewards-lite'),
254 'tabs' => array(
255 'wr_loyalty' => array(
256 'title' => __("Points and Rewards", 'woorewards-lite'),
257 'id' => 'wr_loyalty',
258 'icon' => 'lws-icon-present',
259 'groups' => $this->getLoyaltyGroups()
260 ),
261 'wr_othersettings' => array(
262 'title' => __("Other Settings", 'woorewards-lite'),
263 'id' => 'wr_othersettings',
264 'icon' => 'lws-icon-adv-settings',
265 'groups' => $this->getSettingsGroups()
266 )
267 )
268 );
269 }
270
271 protected function getWizardPage()
272 {
273 return array(
274 'title' => __("Wizard", 'woorewards-lite'),
275 'subtitle' => __("Wizard", 'woorewards-lite'),
276 'id' => LWS_WIZARD_SUMMONER . LWS_WOOREWARDS_PAGE,
277 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
278 'color' => '#00B7EB',
279 'image' => LWS_WOOREWARDS_IMG . '/r-wizard.png',
280 'description' => __("The wizard page lets you setup your points and rewards program in a few minutes", 'woorewards-lite'),
281 );
282 }
283
284 protected function getSettingsGroups()
285 {
286 return array(
287 'settings' => array(
288 'id' => 'settings',
289 'icon' => 'lws-icon-settings-gear',
290 'title' => __("General settings", 'woorewards-lite'),
291 'text' => __("Check the options below according to your needs. If you want to exclude shipping fees from points calculation, it can be done inside your loyalty systems.", 'woorewards-lite'),
292 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('adv-features')),
293 'fields' => array(
294 'inc_taxes' => array(
295 'id' => 'lws_woorewards_order_amount_includes_taxes',
296 'title' => __("Includes taxes", 'woorewards-lite'),
297 'type' => 'box',
298 'extra' => array(
299 'layout' => 'toggle',
300 'help' => __("If checked, taxes will be included in the points earned when spending money", 'woorewards-lite'),
301 )
302 ),
303 'c_prefix' => array(
304 'id' => 'lws_woorewards_reward_coupon_code_prefix',
305 'title' => __("Coupon prefix", 'woorewards-lite'),
306 'type' => 'text',
307 'extra' => array(
308 'size' => '10',
309 'help' => __("Set a prefix code that will be added on all coupon codes generated by MyRewards", 'woorewards-lite'),
310 )
311 ),
312 'c_length' => array(
313 'id' => 'lws_woorewards_coupon_code_length',
314 'title' => __("Coupon code length", 'woorewards-lite'),
315 'type' => 'text',
316 'extra' => array(
317 'size' => '3',
318 'default' => '10',
319 'placeholder' => '10',
320 'help' => __("Set the length of the generated coupon code. The length comes in addition to the code prefix.", 'woorewards-lite')
321 /* translators: %s: minimum code length */
322 . ' ' . sprintf(__("Minimum length is %s.", 'woorewards-lite'), \LWS\WOOREWARDS\Unlockables\Coupon::COUPON_CODE_MIN_LENGTH),
323 )
324 ),
325 'order_state' => array(
326 'id' => 'lws_woorewards_points_distribution_status',
327 'title' => __("Order statuses for points", 'woorewards-lite'),
328 'type' => 'lacchecklist',
329 'extra' => array(
330 'ajax' => 'lws_adminpanel_get_order_status',
331 'help' => __("Default state to get points is the processing order status.<br/>If you want to use other statuses instead (recommanded), select them here", 'woorewards-lite'),
332 )
333 ),
334 'deep_usersearch' => array(
335 'id' => 'lws_woorewards_admin_userspoints_deep_search',
336 'title' => __("Deep customer search", 'woorewards-lite'),
337 'type' => 'box',
338 'extra' => array(
339 'layout' => 'toggle',
340 'default' => 'on',
341 'help' => __("If you have troubles with searching in WooRewards Customers administration screen, disable this option. This will speed up the search but it will take less data into account.", 'woorewards-lite'),
342 )
343 ),
344 'show_priorities' => array(
345 'id' => 'lws_woorewards_show_loading_order_and_priority',
346 'title' => __("Show loading orders", 'woorewards-lite'),
347 'type' => 'box',
348 'extra' => array(
349 'layout' => 'toggle',
350 'help' => __("For some advanced setups, managing loyalty system loading order and event trigger priority could be meaningful.", 'woorewards-lite'),
351 )
352 ),
353 )
354 ),
355 'pointsoncart' => array(
356 'id' => 'pointsoncart',
357 'icon' => 'lws-icon-coins',
358 'title' => __("Order statuses to consume used points", 'woorewards-lite'),
359 'text' => __("Points used to get a discount are consumed when order status changes.", 'woorewards-lite'),
360 'fields' => array(
361 'order_state' => array(
362 'id' => 'lws_woorewards_pointdiscount_pay_order_status',
363 'title' => __("Order statuses to pay discount", 'woorewards-lite'),
364 'type' => 'lacchecklist',
365 'extra' => array(
366 'ajax' => 'lws_adminpanel_get_order_status',
367 'default' => array('processing', 'completed'),
368 )
369 ),
370 'failure' => array(
371 'id' => 'lws_woorewards_pointdiscount_pay_order_failure',
372 'title' => __("Order status on payment failure", 'woorewards-lite'),
373 'type' => 'lacselect',
374 'extra' => array(
375 'mode' => 'select',
376 'source' => array(
377 array('value' => '_', 'label' => __("[do nothing]", 'woorewards-lite'))
378 ),
379 'ajax' => 'lws_adminpanel_get_order_status',
380 'default' => 'failed',
381 'help' => __("Change order status if points cannot be paid after all.", 'woorewards-lite'),
382 )
383 ),
384 )
385 ),
386 'sponsorship' => array(
387 'id' => 'sponsorship',
388 'icon' => 'lws-icon-handshake',
389 'color' => '#669876',
390 'title' => __("Referral Features", 'woorewards-lite'),
391 'text' => __("Here, you'll find the different tools customers can use to refer their friends and the reward given to referred users.", 'woorewards-lite') .
392 __("To reward the referrers, either use the dedicated wizard or select an appropriate earning method inside a points and rewards system.", 'woorewards-lite'),
393 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('referral')),
394 'fields' => array(
395 'enable' => array(
396 'id' => 'lws_woorewards_event_enabled_sponsorship',
397 'title' => __("Enable Referrals", 'woorewards-lite'),
398 'type' => 'box',
399 'extra' => array(
400 'layout' => 'toggle',
401 'default' => 'on'
402 )
403 ),
404 'enableReferral' => array(
405 'id' => 'lws_woorewards_referral_back_give_sponsorship',
406 'type' => 'box',
407 'title' => __("Allow referrals via referral link", 'woorewards-lite'),
408 'extra' => array(
409 'default' => 'on',
410 'layout' => 'toggle',
411 'help' => __("When a visitor comes from a referral link and registers, he will be referred by the user that posted the link.", 'woorewards-lite')
412 )
413 ),
414 'tinify' => array(
415 'id' => 'lws_woorewards_sponsorship_tinify_enabled',
416 'title' => __("Try to shorten the referral URL", 'woorewards-lite'),
417 'type' => 'box',
418 'extra' => array(
419 'help' => __('Disable that feature if you encounter plugin conflicts or redirection problems. Disable that feature makes bigger and less readable QR codes.', 'woorewards-lite'),
420 'class' => 'lws_checkbox',
421 'default' => '',
422 'id' => 'lws_woorewards_sponsorship_tinify_enabled',
423 )
424 ),
425 'tiny' => array(
426 'id' => 'lws_woorewards_sponsorship_short_url',
427 'title' => __("Alternative Short Site URL", 'woorewards-lite'),
428 'type' => 'text',
429 'extra' => array(
430 'help' => __('To make the QR-Code as simple as possible, you can specify a shorter version of your site URL here that will be used as base for the image generation.', 'woorewards-lite'),
431 'placeholder' => \site_url(),
432 ),
433 'require' => array('selector' => '#lws_woorewards_sponsorship_tinify_enabled', 'value' => 'on'),
434 ),
435 'max' => array(
436 'id' => 'lws_wooreward_max_sponsorship_count',
437 'title' => __("Max referrals per customer", 'woorewards-lite'),
438 'type' => 'text',
439 'extra' => array(
440 'pattern' => '\d+',
441 'default' => '0',
442 'help' => __("Set the maximum referrals allowed for users. No restriction on empty value or zero (0).", 'woorewards-lite')
443 )
444 ),
445 )
446 ),
447 );
448 }
449
450 protected function getAppearancePage()
451 {
452 require_once LWS_WOOREWARDS_INCLUDES . '/ui/adminscreens/styling.php';
453
454 $appearancePage = array(
455 'title' => __("Appearance", 'woorewards-lite'),
456 'subtitle' => __("Appearance", 'woorewards-lite'),
457 'id' => LWS_WOOREWARDS_PAGE . '.appearance',
458 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
459 'color' => '#4CBB41',
460 'image' => LWS_WOOREWARDS_IMG . '/r-appearance.png',
461 'description' => __("Use this page to display loyalty content to your customers on your website", 'woorewards-lite'),
462 'tabs' => array(
463 'woocommerce' => $this->getWoocommerceTab(),
464 'shortcodes' => $this->getShortcodesTab(),
465 'sty_mails' => array(
466 'id' => 'sty_mails',
467 'title' => __("Emails", 'woorewards-lite'),
468 'icon' => 'lws-icon-letter',
469 'groups' => \lws_mail_settings(\apply_filters('lws_woorewards_mails', array()))
470 ),
471 'styling' => \LWS\WOOREWARDS\Ui\AdminScreens\Styling::getTab(true)
472 )
473 );
474
475 if (\LWS\WOOREWARDS\Conveniences::instance()->isLegacyShown('4.7.0')) {
476 $appearancePage['tabs']['legacy'] = $this->getLegacyTab();
477 }
478 return $appearancePage;
479 }
480
481 protected function getSystemPage()
482 {
483 $systemPage = array(
484 'title' => __("System", 'woorewards-lite'),
485 'subtitle' => __("System", 'woorewards-lite'),
486 'id' => LWS_WOOREWARDS_PAGE . '.system',
487 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
488 'color' => '#7958A5',
489 'image' => LWS_WOOREWARDS_IMG . '/r-system.png',
490 'description' => __("Export or import your customers points, process past orders in this page", 'woorewards-lite'),
491 'delayedFunction' => array($this, 'showCronStatus'),
492 'tabs' => array(
493 'data_management' => array(
494 'id' => 'data_management',
495 'title' => __("Data Management", 'woorewards-lite'),
496 'icon' => 'lws-icon-components',
497 'groups' => array(
498 'wc_old_orders' => array(
499 'id' => 'wc_old_orders',
500 'icon' => 'lws-icon-repeat',
501 'title' => __("Give Points for Past orders", 'woorewards-lite'),
502 'text' => __("If you want to give points for orders that pre-existed your loyalty system, you can do it here", 'woorewards-lite') . '<br/>',
503 'fields' => array(),
504 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('past-orders'))
505 ),
506 )
507 ),
508 )
509 );
510
511 $systemPage['tabs']['data_management']['groups']['wc_old_orders']['text'] .= __("This operation can take several minutes. Depending on your server configuration, you should run this operation several times on small subsets of orders.", 'woorewards-lite');
512 if (\LWS\Adminpanel\Tools\Conveniences::isHPOS())
513 $url = \add_query_arg('page', 'wc-orders', \admin_url('admin.php'));
514 else
515 $url = \add_query_arg('post_type', 'shop_order', \admin_url('edit.php'));
516
517 $systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['link'] = array(
518 'id' => 'redirect_to_order_bulk',
519 'title' => '',
520 'type' => 'custom',
521 'extra' => array(
522 'gizmo' => true,
523 'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(array(
524 'tag' => 'ul',
525 sprintf('<b style="color: #dd1a1a;">%s</b>', __("If your loyalty program is live, this could lead to lots of rewards being generated and lots of emails being sent", 'woorewards-lite')),
526 sprintf('<b style="color: #dd1a1a;">%s</b>', __("Please make sure you reviewed all the settings before launching this procedure.", 'woorewards-lite')),
527 sprintf('<b style="color: #dd1a1a;">%s</b>', __("Please ensure you agree to send emails to your customers about there activities in loyalty systems or deactivate relevant emails first.", 'woorewards-lite')),
528 sprintf('<a style="color: #dd1a1a;" href="%s" target="_blank">%s</a>', \esc_attr(\add_query_arg(array(
529 'page' => LWS_WOOREWARDS_PAGE . '.appearance',
530 'tab' => 'sty_mails',
531 ), \admin_url('admin.php'))), __("See WooRewards emails settings", 'woorewards-lite')),
532 ), array(
533 /* translators: %s: URL to WooCommerce Orders */
534 sprintf(__("Go to the <a href='%s'>WooCommerce Orders list</a>.", 'woorewards-lite'), \esc_attr($url)),
535 __("Check the box at left of the orders to process.", 'woorewards-lite'),
536 /* translators: %s: bulk action label */
537 sprintf(__("In the <b>Bulk Actions</b> drop-list, pick <b>%s</b>.", 'woorewards-lite'), \LWS\WOOREWARDS\Ui\Woocommerce\OrdersBulk::getLabel()),
538 __("Then, press the <b>Apply</b> button.", 'woorewards-lite'),
539 ))),
540 )
541 );
542
543 //if ((isset($_GET['legacy']) && 'yes' === $_GET['legacy']) || (isset($_POST['button']) && 'trigger_orders' === $_POST['button'])) {
544 //$systemPage['tabs']['data_management']['groups']['wc_old_orders']['text'] .= __("This operation can take several minutes. Depending on your server configuration and date range, you should run this operation several times on short dates ranges.", 'woorewards-lite');
545
546 $systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['separator'] = array(
547 'id' => 'past_order_per_date_separator',
548 'title' => '',
549 'type' => 'custom',
550 'extra' => array(
551 'gizmo' => true,
552 'separator' => true,
553 'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(
554 __("Or use our date range selector", 'woorewards-lite'),
555 array('tag' => 'small',
556 __("(Don't be too greedy. Depending on your sales volume, cut the period into smaller ones or the procedure may stop in timeout. In any case, the same order will not be processed twice.)", 'woorewards-lite'),
557 ),
558 )),
559 )
560 );
561
562 $systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['per_dates'] = array(
563 'id' => 'past_order_per_date_range',
564 'title' => __("Date range", 'woorewards-lite'),
565 'type' => 'custom',
566 'extra' => array(
567 'gizmo' => true,
568 'content' => function(){
569 return sprintf(
570 "From %s to %s",
571 \LWS\Adminpanel\Pages\Field\Input::compose('date_min', array(
572 'type' => 'date',
573 'gizmo' => true,
574 'class' => 'lws-ignore-confirm',
575 'default' => \date_create()->sub(new \DateInterval('P1M'))->format('Y-m-d'),
576 )), \LWS\Adminpanel\Pages\Field\Input::compose('date_max', array(
577 'type' => 'date',
578 'gizmo' => true,
579 'class' => 'lws-ignore-confirm',
580 'default' => \gmdate('Y-m-d'),
581 ))
582 );
583 },
584 )
585 );
586 $systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['trigger_orders'] = array(
587 'id' => 'trigger_orders',
588 'title' => __("Launch the procedure", 'woorewards-lite'),
589 'type' => 'button',
590 'extra' => array(
591 'callback' => array($this, 'forceOldOrdersTrigger')
592 ),
593 );
594 //}
595
596 require_once LWS_WOOREWARDS_INCLUDES . '/ui/adminscreens/pointsmanagement.php';
597 \LWS\WOOREWARDS\Ui\AdminScreens\PointsManagement::mergeGroups($systemPage['tabs']['data_management']['groups']);
598
599 $systemPage['tabs']['data_management']['groups']['restore_points'] = array(
600 'id' => 'restore_points',
601 'title' => __("Restore Points to Historical Date", 'woorewards-lite'),
602 'icon' => 'lws-icon-time-machine',
603 'class' => 'half',
604 'text' => __("Rollback all users' point balances to their state on a specific date.", 'woorewards-lite')
605 . '<br/>' . __("This analyzes the history table and adjusts current balances accordingly.", 'woorewards-lite')
606 . '<br/><b style="color: #d76f00;">' . __("Note: New history entries will be created showing the adjustment.", 'woorewards-lite') . '</b>',
607 'fields' => array(
608 'restore_pool' => array(
609 'id' => 'restore_points_pool',
610 'title' => __("Select points and rewards system", 'woorewards-lite'),
611 'type' => 'lacselect',
612 'extra' => array(
613 'gizmo' => true,
614 'class' => 'lws-ignore-confirm',
615 'ajax' => 'lws_woorewards_pool_list',
616 'required' => true,
617 'help' => __("Select the loyalty system to restore. Only one system can be restored at a time.", 'woorewards-lite'),
618 ),
619 ),
620 'restore_date' => array(
621 'id' => 'restore_points_date',
622 'title' => __("Restore to date", 'woorewards-lite'),
623 'type' => 'input',
624 'extra' => array(
625 'gizmo' => true,
626 'type' => 'date',
627 'class' => 'lws-ignore-confirm',
628 'required' => true,
629 'max' => \gmdate('Y-m-d'),
630 'help' => __("Select the target date for restoration.", 'woorewards-lite'),
631 ),
632 ),
633 'restore_time' => array(
634 'id' => 'restore_points_time',
635 'title' => __("Restore to time", 'woorewards-lite'),
636 'type' => 'input',
637 'extra' => array(
638 'gizmo' => true,
639 'type' => 'time',
640 'class' => 'lws-ignore-confirm',
641 'value' => '23:59',
642 'help' => __("Select the specific time. Points will be restored to their balance at this exact time. Default is end of day (23:59).", 'woorewards-lite'),
643 ),
644 ),
645 'trigger_restore' => array(
646 'id' => 'trigger_restore_points',
647 'title' => __("Restore Points", 'woorewards-lite'),
648 'type' => 'button',
649 'extra' => array(
650 'gizmo' => true,
651 'callback' => array($this, 'restorePointsToDate')
652 ),
653 ),
654 )
655 );
656
657 $systemPage['tabs']['data_management']['groups']['delete'] = array(
658 'id' => 'delete',
659 'title' => __("Delete all data", 'woorewards-lite'),
660 'icon' => 'lws-icon-delete-forever',
661 'class' => 'half',
662 'text' => __("Remove all loyalty systems, user points and all MyRewards related data.", 'woorewards-lite')
663 . '<br/>' . __("Use this feature with care since this action is <b>irreversible</b>.", 'woorewards-lite'),
664 'fields' => array(
665 'trigger_delete' => array(
666 'id' => 'trigger_delete_all_woorewards',
667 'title' => __("Delete All Data", 'woorewards-lite'),
668 'type' => 'button',
669 'extra' => array(
670 'callback' => array($this, 'deleteAllData')
671 ),
672 ),
673 )
674 );
675
676 return $systemPage;
677 }
678
679 function showCronStatus()
680 {
681 $text = array();
682 if ($next = \intval(\wp_next_scheduled('lws_woorewards_daily_event'))) {
683 $d = \date_create('now', \LWS_WooRewards::getSiteTimezone())->setTimestamp($next);
684 /* translators: %1$s: date and time, %2$s: UTC offset */
685 $text[] = sprintf(__('Next CRON action planned at %1$s (UTC%2$s).', 'woorewards-lite'), $d->format('Y-m-d H:i'), $d->format('P'));
686 } else {
687 $text[] = __('CRON action is not registered. To fix it, deactivate then re-activate this plugin.', 'woorewards-lite');
688 }
689 if ($last = \intval(\get_option('lws_woorewards_last_cron_time'))) {
690 $d = \date_create('now', \LWS_WooRewards::getSiteTimezone())->setTimestamp($last);
691 /* translators: %1$s: date and time, %2$s: UTC offset */
692 $text[] = sprintf(__('Last CRON action ran at %1$s (UTC%2$s).', 'woorewards-lite'), $d->format('Y-m-d H:i'), $d->format('P'));
693 }
694 $text = implode('<br/>', $text);
695 echo wp_kses_post("<div style='padding:20px;gap:20px;text-align:right;'><small>{$text}</small></div>");
696 }
697
698 protected function getProVersionPage()
699 {
700 $page = array(
701 'title' => __("Pro Version", 'woorewards-lite'),
702 'subtitle' => "<div style='padding:2px 10px 4px 10px;background-color:#526981;color:#fff;text-align:center;font-weight:bold'>" . __("Pro Version", 'woorewards-lite') . "</div>",
703 'pagetitle' => __("Pro Version", 'woorewards-lite'),
704 'id' => LWS_WOOREWARDS_PAGE . '-proversion',
705 'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
706 'color' => '#4f9bbf',
707 'nosave' => true,
708 'image' => LWS_WOOREWARDS_IMG . '/r-pro.png',
709 'description' => __("Unlock this plugin's full potential by switching to the pro version. Check all the features and discover how to install it", 'woorewards-lite'),
710 );
711
712 if ($page['id'] != $this->getCurrentPage())
713 return $page;
714
715 $installurl = \esc_attr(\admin_url('plugin-install.php'));
716 $install = "<div class='teaser'>"
717 . "<div class='teaser-div'>"
718 . "Follow these instructions to install the pro version and activate it"
719 . "</div>"
720 . "<ul class='teaser-list'>"
721 . "<li>You received an email following your order with a download link.<b>Click the link</b> to download the plugin's zip file</li>"
722 . "<li>If you can't find the email, log into <a href='https://plugins.longwatchstudio.com/my-account' target='_blank'>your account</a> and go to the <b>Downloads</b> section. Download the zip file</li>"
723 . "<li>In your WordPress administration, go to <a href='{$installurl}' target='_blank'>the plugins installation page</a> and click the <b>Upload Plugin</b> button. In the dialog, select the plugin's zip file and click <b>Install Now</b></li>"
724 . "<li>When the process is complete, choose to <b>Replace the existing version with the new one</b>, even if the version number is the same</li>"
725 . "<li>Activate the plugin</li>"
726 . "<li>Now, go to <b>WooRewards &rarr; System &rarr; License Management</b>, paste your license key and click on <b>Activate</b></li>"
727 . "<li>That's it, you now have the pro version installed and active.</li>"
728 . "</ul>"
729 . "</div>";
730
731 $content = "<div class='teaser'>"
732 . "<div class='teaser-div'>"
733 . "MyRewards Pro extends MyRewards features and offers a wide variety of new possibilities that will help you retain your existing customers and attract new ones."
734 . "</div>"
735 . "<ul class='teaser-list'>"
736 . "<li><b>20+ Action to earn points</b><span> - Choose in a large variety of methods to earn points to engage your customers in a meaningful way.</span></li>"
737 . "<li><b>Infinite points and rewards systems</b><span> - You can create different loyalty programs for different purposes and even for different customers</span></li>"
738 . "<li><b>Ambassador System</b><span> - Transform your customers into real ambassadors by rewarding them for each new customer they bring or for each dollar spent by them</span></li>"
739 . "<li><b>Points expiration</b><span> - Choose between 3 different methods for points expiration : Inactivity, Periodical, Transactional</span></li>"
740 . "<li><b>Events</b><span> - Create timed loyalty programs for special occasions like Christmas, Easter, your website's anniversary ...</span></li>"
741 . "<li><b>Your Points, Your name</b><span> - For each loyalty program, you have the option to name the points how you want, or even use an image instead of a name</span></li>"
742 . "<li><b>WooCommerce integration</b><span> - Display loyalty information inside product pages, my account pages, cart and checkout pages and even in WooCommerce emails</span></li>"
743 . "<li><b>Wizards</b><span> - Earn time by creating quickly new events or loyalty programs thanks to our predefined wizards. They will guide you through all the process</span></li>"
744 . "<li><b>Points Import/Export</b><span> - You want to switch from another loyalty plugin ? No problem, MyRewards includes an import/export feature, even for other plugins</span></li>"
745 . "<li><b>Social Media</b><span> - Reward customers when they share your content on social media OR only reward them if it brings new visitors to your website</span></li>"
746 . "<li><b>Customers Management</b><span> - Manage your customers' points, rewards and levels</span></li>"
747 . "<li><b>REST API</b><span> - Want to connect a third party software ? It's possible with the included REST API</span></li>"
748 . "<li><b>WooCommerce Subscriptions compatibility</b><span> - Give points for initial subscriptions and for subscriptions renewals</span></li>"
749 . "<li><b>Shortcodes</b><span> - With more than 20 shortcodes to choose from, you always find the one you need to display the right information at the right place</span></li>"
750 . "<li><b>Widgets</b><span> - If you prefer to use widgets, then you will find all the necessary widgets for your needs</span></li>"
751 . "<li><b>Emails</b><span> - Decide which emails to send between 7 sorts and customize them</span></li>"
752 . "<li><b>Badges and Achievements</b><span> - Play with your customers' pride by adding badges and achievements to your website</span></li>"
753 . "<li><b>Sponsorship/Referral</b><span> - Let customers sponsor new customers through emails, QR Codes or social shares</span></li>"
754 . "<li><b>Order refunds</b><span> - Remove previously earned points when an order is cancelled or refunded</span></li>"
755 . "</ul>"
756 . "<div class='teaser-button'>"
757 . "<a class='teaser-link' href='https://plugins.longwatchstudio.com/product/woorewards/' target='_blank'>Discover MyRewards Pro</a>"
758 . "</div>"
759 . "</div>";
760
761 $page['tabs'] = array(
762 'pro_version' => array(
763 'id' => 'pro_version',
764 'title' => __("Pro Version", 'woorewards-lite'),
765 'icon' => 'lws-icon-cart-2',
766 'groups' => array(
767 'install' => array(
768 'id' => 'install',
769 'title' => __("Pro Version - How to Install", 'woorewards-lite'),
770 'icon' => 'lws-icon-settings-gear',
771 'color' => '#40aa8e',
772 'text' => __("If you already purchased the pro version, follow the instructions below to install and activate it", 'woorewards-lite'),
773 'fields' => array(
774 'install_instructions' => array(
775 'id' => 'install_instructions',
776 'type' => 'custom',
777 'extra' => array(
778 'gizmo' => true,
779 'content' => $install,
780 ),
781 ),
782 )
783 ),
784 'teaser' => array(
785 'id' => 'teaser',
786 'title' => __("Pro Version - Test if for free for 1 month !", 'woorewards-lite'),
787 'icon' => 'lws-icon-cart-2',
788 'color' => '#408aae',
789 'text' => __("Discover the features of the pro version and how it will help your online store grow.", 'woorewards-lite'),
790 'fields' => array(
791 'pro_description' => array(
792 'id' => 'pro_description',
793 'type' => 'custom',
794 'extra' => array(
795 'gizmo' => true,
796 'content' => $content,
797 ),
798 ),
799 )
800 ),
801 )
802 ),
803 );
804 return $page;
805 }
806
807 protected function getWoocommerceTab()
808 {
809 $tab = array(
810 'id' => 'woocommerce',
811 'title' => __("WooCommerce", 'woorewards-lite'),
812 'icon' => 'lws-icon-cart-2',
813 'groups' => array(
814 'cart' => array(
815 'id' => 'wr_cart_content',
816 'icon' => 'lws-icon-cart-2',
817 'color' => '#425981',
818 'title' => __("Cart Page Content", 'woorewards-lite'),
819 'text' => __("Select what and where you want to display content on the WooCommerce Cart Page. You can even display other plugins shortcodes", 'woorewards-lite'),
820 'fields' => array(),
821 ),
822 'checkout' => array(
823 'id' => 'wr_checkout_content',
824 'icon' => 'lws-icon-checkmark',
825 'color' => '#425981',
826 'title' => __("Checkout Page Content", 'woorewards-lite'),
827 'text' => __("Select what and where you want to display content on the WooCommerce Checkout Page. You can even display other plugins shortcodes", 'woorewards-lite'),
828 'fields' => array(),
829 )
830 )
831 );
832
833 $isCartUseBlocs = \LWS\Adminpanel\Tools\Conveniences::isCartUseBlocs();
834 if ($isCartUseBlocs) {
835 $tab['groups']['cart']['fields']['disclamer'] = array(
836 'id' => 'disclamer',
837 'type' => 'custom',
838 'extra' => array(
839 'gizmo' => true,
840 'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(
841 'tag' => 'b style="color:#0a41c6;"',
842 __("Fields below are for legacy [woocommerce_cart] shortcode.", 'woorewards-lite'),
843 __("It seems your Cart page is setup with Woocommerce blocks.", 'woorewards-lite'),
844 __("Please edit the WooCommerce Cart page and insert our shortcodes directly in it.", 'woorewards-lite'),
845 )),
846 )
847 );
848 }
849 $isCheckoutUseBlocs = \LWS\Adminpanel\Tools\Conveniences::isCheckoutUseBlocs();
850 if ($isCheckoutUseBlocs) {
851 $tab['groups']['checkout']['fields']['disclamer'] = array(
852 'id' => 'disclamer',
853 'type' => 'custom',
854 'extra' => array(
855 'gizmo' => true,
856 'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(
857 'tag' => 'b style="color:#0a41c6;"',
858 __("Fields below are for legacy [woocommerce_checkout] shortcode.", 'woorewards-lite'),
859 __("It seems your Checkout page is setup with Woocommerce blocks.", 'woorewards-lite'),
860 __("Please edit the WooCommerce Checkout page and insert our shortcodes directly in it.", 'woorewards-lite'),
861 )),
862 )
863 );
864 }
865
866 foreach (\LWS\WOOREWARDS\Ui\Woocommerce\CartCheckoutContent::getSettings() as $hook => $settings) {
867 $field = array(
868 'id' => $settings['option'],
869 'title' => $settings['title'],
870 'type' => 'wpeditor',
871 'extra' => array(
872 'editor_height' => 30,
873 'wpml' => $settings['wpml'],
874 )
875 );
876
877 if ($isCartUseBlocs && false !== \strpos($field['id'], '_cart_')) {
878 $field['type'] = 'textarea';
879 $field['extra']['disabled'] = true;
880 $field['extra']['rows'] = 2;
881 }
882 if ($isCheckoutUseBlocs && false !== \strpos($field['id'], '_checkout_')) {
883 $field['type'] = 'textarea';
884 $field['extra']['disabled'] = true;
885 $field['extra']['rows'] = 2;
886 }
887
888 $tab['groups'][$settings['page']]['fields'][$hook] = $field;
889 }
890
891 return $tab;
892 }
893
894 protected function getShortcodesTab()
895 {
896 $shortcodesTab = array(
897 'id' => 'shortcodes',
898 'title' => __("Shortcodes", 'woorewards-lite'),
899 'icon' => 'lws-icon-shortcode',
900 'groups' => array(
901 'shortcodes' => array(
902 'id' => 'shortcodes',
903 'title' => __('Shortcodes', 'woorewards-lite'),
904 'icon' => 'lws-icon-shortcode',
905 'text' => __("In this section, you will find various shortcodes you can use on your website.", 'woorewards-lite'),
906 'fields' => \apply_filters('lws_woorewards_referral_shortcodes',
907 \apply_filters('lws_woorewards_shortcodes', array())
908 )
909 ),
910 )
911 );
912 return $shortcodesTab;
913 }
914
915 protected function getLegacyTab()
916 {
917 return array(
918 'id' => 'legacy',
919 'title' => __("Legacy", 'woorewards-lite'),
920 'icon' => 'lws-icon-components',
921 'groups' => array(
922 'pointsoncart' => array(
923 'id' => 'pointsoncart',
924 'icon' => 'lws-icon-coins',
925 'title' => __("Points On Cart", 'woorewards-lite'),
926 'text' => __("Select where the Points on Cart tool will be displayed and how it will look", 'woorewards-lite'),
927 'fields' => array(
928 'cartdisplay' => array(
929 'id' => 'lws_woorewards_points_to_cart_pos',
930 'title' => __("Cart Display", 'woorewards-lite'),
931 'type' => 'lacselect',
932 'extra' => array(
933 'mode' => 'select',
934 'notnull' => true,
935 'maxwidth' => '400px',
936 'source' => array(
937 array('value' => 'not_displayed', 'label' => __("Not displayed at all", 'woorewards-lite')),
938 array('value' => 'after_products', 'label' => __("Between products and totals", 'woorewards-lite')),
939 array('value' => 'cart_collaterals', 'label' => __("Aside from cart totals", 'woorewards-lite')),
940 ),
941 'default' => 'not_displayed',
942 'help' => __("The following options are used to decide where and how the Points on Cart tool will be displayed in the cart page", 'woorewards-lite'),
943 )
944 ),
945 'cartreload' => array(
946 'id' => 'lws_woorewards_points_to_cart_reload',
947 'title' => __("Reload cart page after amount modification", 'woorewards-lite'),
948 'type' => 'box',
949 'extra' => array(
950 'layout' => 'toggle',
951 'tooltips' => __("By default, changing the amount will provoke a javascript (ajax) update. Check this box if the default behavior doesn't work.", 'woorewards-lite'),
952 )
953 ),
954 'checkoutdisplay' => array(
955 'id' => 'lws_woorewards_points_to_checkout_pos',
956 'title' => __("Checkout Display", 'woorewards-lite'),
957 'type' => 'lacselect',
958 'extra' => array(
959 'mode' => 'select',
960 'notnull' => true,
961 'maxwidth' => '400px',
962 'source' => array(
963 array('value' => 'not_displayed', 'label' => __("Not displayed at all", 'woorewards-lite')),
964 array('value' => 'top_page', 'label' => __("Top of the page", 'woorewards-lite')),
965 array('value' => 'before_customer', 'label' => __("Before customer details", 'woorewards-lite')),
966 array('value' => 'before_review', 'label' => __("Before order review", 'woorewards-lite')),
967 ),
968 'default' => 'not_displayed',
969 'help' => __("The following options are used to decide where and how the Points on Cart tool will be displayed in the checkout page", 'woorewards-lite'),
970 )
971 ),
972 'checkoutreload' => array(
973 'id' => 'lws_woorewards_points_to_checkout_reload',
974 'title' => __("Reload checkout page after amount modification", 'woorewards-lite'),
975 'type' => 'box',
976 'extra' => array(
977 'layout' => 'toggle',
978 'tooltips' => __("By default, changing the amount will provoke a javascript (ajax) update. Check this box if the default behavior doesn't work.", 'woorewards-lite'),
979 )
980 ),
981 'pointsoncartheader' => array(
982 'id' => 'lws_wooreward_points_cart_header',
983 'title' => __("Tool Header", 'woorewards-lite'),
984 'type' => 'text',
985 'extra' => array(
986 'placeholder' => __('Loyalty points discount', 'woorewards-lite'),
987 'size' => '30',
988 'wpml' => 'WooRewards - Points On Cart Action - Header',
989 )
990 ),
991 array(
992 'id' => 'lws_woorewards_points_to_cart_style',
993 'type' => 'stygen',
994 'extra' => array(
995 'purpose' => 'filter',
996 'template' => 'lws_woorewards_points_to_cart',
997 'html' => false,
998 'css' => LWS_WOOREWARDS_CSS . '/templates/pointsoncart.css',
999 'help' => __("Use the styling tool to change the tool's frontend appearance", 'woorewards-lite'),
1000 'subids' => array(
1001 'lws_woorewards_points_to_cart_action_balance' => "WooRewards - Points On Cart Action - Balance",
1002 'lws_woorewards_points_to_cart_action_use' => "WooRewards - Points On Cart Action - Use",
1003 'lws_woorewards_points_to_cart_action_update' => "WooRewards - Points On Cart Action - Update",
1004 'lws_woorewards_points_to_cart_action_max' => "WooRewards - Points On Cart Action - Max",
1005 ),
1006 )
1007 )
1008 )
1009 ),
1010 'showpoints' => array(
1011 'id' => 'showpoints',
1012 'icon' => 'lws-icon-components',
1013 'title' => __("Display Points Widget", 'woorewards-lite'),
1014 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('disp-points')),
1015 'text' => "<strong>" . __("Legacy : This widget is no longer maintained or updated. Use the points balance shortcode instead.", 'woorewards-lite') . "</strong>",
1016 'fields' => array(
1017 'spunconnected' => array(
1018 'id' => 'lws_wooreward_showpoints_nouser',
1019 'title' => __("Text displayed if user not connected", 'woorewards-lite'),
1020 'type' => 'text',
1021 'extra' => array(
1022 'size' => '50',
1023 'placeholder' => __("Please log in if you want to see your loyalty points", 'woorewards-lite'),
1024 )
1025 ),
1026 'showpoints' => array(
1027 'id' => 'lws_woorewards_displaypoints_template',
1028 'type' => 'stygen',
1029 'extra' => array(
1030 'purpose' => 'filter',
1031 'template' => 'wr_display_points',
1032 'html' => false,
1033 'css' => LWS_WOOREWARDS_CSS . '/templates/displaypoints.css',
1034 'help' => __("Here you can customize the look and displayed text of the shortcode/widget", 'woorewards-lite'),
1035 'subids' => array(
1036 'lws_woorewards_displaypoints_title' => "WooRewards Show Points - title", // no translation on purpose
1037 'lws_woorewards_button_more_details' => "WooRewards Show Points - details", // no translation on purpose
1038 )
1039 )
1040 ),
1041 )
1042 ),
1043 'shortcodes' => array(
1044 'id' => 'shortcodes',
1045 'title' => __('Shortcodes', 'woorewards-lite'),
1046 'icon' => 'lws-icon-shortcode',
1047 'text' => __("These shortcodes are deprecated and are kept here for compatibility. Try to replace them with other shortcodes", 'woorewards-lite'),
1048 'fields' => array(
1049 'simplepoints' => array(
1050 'id' => 'lws_woorewards_sc_simple_points',
1051 'title' => __("Simple Points Display", 'woorewards-lite'),
1052 'type' => 'shortcode',
1053 'extra' => array(
1054 'shortcode' => '[wr_simple_points]',
1055 'description' => __("This simple shortcode is used to display the user's points with no decoration.", 'woorewards-lite') . "<br/>" .
1056 __("This is very convenient if you want to display points within a phrase for example.", 'woorewards-lite'),
1057 'options' => array(),
1058 'flags' => array('current_user_id'),
1059 )
1060 ),
1061 'showpoints' => array(
1062 'id' => 'lws_woorewards_sc_show_points',
1063 'title' => __("Display Points", 'woorewards-lite'),
1064 'type' => 'shortcode',
1065 'extra' => array(
1066 'shortcode' => '[wr_show_points title="your title"]',
1067 'description' => __("This shortcode shows to customers the points they have on a loyalty system.", 'woorewards-lite'),
1068 'options' => array(
1069 array(
1070 'option' => 'title',
1071 'desc' => __("The text displayed before the points.", 'woorewards-lite'),
1072 ),
1073 array(
1074 'option' => 'show_currency',
1075 'desc' => __("(Optional) If set, the number of points displayed will show the points currency.", 'woorewards-lite'),
1076 ),
1077 ),
1078 'flags' => array('current_user_id'),
1079 )
1080 ),
1081 ),
1082 ),
1083 )
1084 );
1085 }
1086 /** Tease about pro version.
1087 * Display standard pool settings. */
1088 protected function getLoyaltyGroups()
1089 {
1090 $groups = array();
1091
1092 if (!\LWS\Adminpanel\Tools\Conveniences::isWC() && (!defined('LWS_WOOREWARDS_ACTIVATED') || !LWS_WOOREWARDS_ACTIVATED)) {
1093 $groups['information'] = array(
1094 'id' => 'information',
1095 'title' => __("Information", 'woorewards-lite'),
1096 'text' => __(
1097 "MyRewards Standard uses WooCommerce <i>orders</i> and <i>coupons</i>.
1098 <br/>You should install <a href='https://wordpress.org/plugins/woocommerce/' target='_blank'>WooCommerce</a> to have them active.
1099 <br/>Or <a href='https://plugins.longwatchstudio.com/product/woorewards/' target='_blank'>upgrade <b>MyRewards</b> to the <b>Pro</b> version</a>
1100 and enjoy new ways to earn points (social media, sponsoring... with or without WooCommerce) and a lot of new reward types !",
1101 'woorewards-lite'
1102 )
1103 );
1104 }
1105
1106 // load the default pool
1107 $poolInstance = \LWS\WOOREWARDS\Collections\Pools::instanciate();
1108 $pools = $poolInstance->load(array(
1109 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- required for pool identification
1110 array(
1111 'key' => 'wre_pool_prefab',
1112 'value' => 'yes',
1113 'compare' => 'LIKE'
1114 ),
1115 array(
1116 'key' => 'wre_pool_type',
1117 'value' => \LWS\WOOREWARDS\Core\Pool::T_STANDARD,
1118 'compare' => 'LIKE'
1119 )
1120 )
1121 ));
1122
1123 if ($pools->count() <= 0) {
1124 $text = '';
1125 if (!(defined('LWS_WOOREWARDS_ACTIVATED') && LWS_WOOREWARDS_ACTIVATED)) {
1126 $allPools = $poolInstance->load(array('deep' => false));
1127 if ($allPools->count() > 0) {
1128 $text .= sprintf(
1129 "<p style='font-size:16px'>%s<br/><b>%s</b><br/><br/>%s</p>",
1130 __("You are now using the Free Version of WooRewards. However, we detect that you still have Premium Version settings that are not compatible with the Free Version.", 'woorewards-lite'),
1131 __("If you buy a Premium Version License and activate it, it will restore all the Premium Version data (points and rewards systems, user points, settings).", 'woorewards-lite'),
1132 __("If you prefer to only use the free version, please follow the instructions below :", 'woorewards-lite')
1133 );
1134 }
1135 if (defined('LWS_WIZARD_SUMMONER') && LWS_WIZARD_SUMMONER) {
1136 $text .= sprintf(
1137 /* translators: %s: Wizard link */
1138 __("The WooRewards default points and rewards system does not exist. Please run the <a href='%s' class='lws-adm-btn'>wizard</a> tool to create one.", 'woorewards-lite'),
1139 \esc_attr(\add_query_arg(array('page' => LWS_WIZARD_SUMMONER . LWS_WOOREWARDS_PAGE), admin_url('admin.php')))
1140 );
1141 \lws_admin_add_notice(self::NOTICE_NO_POOL, $text, array('level' => 'info', 'dismissible' => true, 'forgettable' => true));
1142 } else {
1143 $text .= __("The MyRewards default points and rewards system does not exist. Try to re-activate this plugin. If the problem persists, contact your administrator.", 'woorewards-lite');
1144 \lws_admin_add_notice(self::NOTICE_NO_POOL, $text, array('level' => 'info', 'dismissible' => true, 'forgettable' => true));
1145 }
1146 }
1147 $groups['failure'] = array(
1148 'id' => 'failure',
1149 'title' => __("Loading failure", 'woorewards-lite'),
1150 'text' => $text,
1151 );
1152 } else {
1153 $prefix = 'lws-wr-pool-option-';
1154 // let dedicated class create options
1155 $pool = $pools->get(0);
1156 $groups = array_merge($groups, array(
1157 'general' => array(
1158 'id' => 'general',
1159 'image' => LWS_WOOREWARDS_IMG . '/ls-settings.png',
1160 'color' => '#7958a5',
1161 'title' => __("General Settings", 'woorewards-lite'),
1162 'fields' => \apply_filters('lws_woorewards_admin_pool_general_settings', array(), $pool),
1163 'text' => __("Before activating your loyalty program, make sure you've read the documentation. You will find links to the documentation on the top right of each group.", 'woorewards-lite'),
1164 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('pools')),
1165 ),
1166 'earning' => array(
1167 'id' => 'earning',
1168 'class' => 'half',
1169 'title' => __("Points", 'woorewards-lite'),
1170 'image' => LWS_WOOREWARDS_IMG . '/ls-earning.png',
1171 'color' => '#38bebe',
1172 'text' => __("Here you can manage how your customers earn loyalty points", 'woorewards-lite'),
1173 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('points')),
1174 'editlist' => \lws_editlist(
1175 'EventList',
1176 \LWS\WOOREWARDS\Ui\Editlists\MultiFormList::ROW_ID,
1177 new \LWS\WOOREWARDS\Ui\Editlists\EventList($pool),
1178 \LWS\Adminpanel\EditList\Modes::MOD
1179 )->setPageDisplay(false)->setCssClass('eventlist')->setRepeatHead(false)
1180 ),
1181 'spending' => array(
1182 'id' => 'spending',
1183 'class' => 'half',
1184 'title' => __("Rewards", 'woorewards-lite'),
1185 'image' => LWS_WOOREWARDS_IMG . '/ls-gift.png',
1186 'color' => '#526981',
1187 'text' => __("Here you can manage the rewards for your customers. Rewards can either be automatically generated WooCommerce Coupons or points usable on cart for immediate discounts", 'woorewards-lite'),
1188 'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('rewards')),
1189 'fields' => array(
1190 'mode' => array(
1191 'id' => $prefix . 'direct_reward_mode',
1192 'type' => (\defined('LWS_WOOREWARDS_ACTIVATED') && LWS_WOOREWARDS_ACTIVATED) ? 'box' : 'hidden',
1193 'title' => __("Reward Type", 'woorewards-lite'),
1194 'extra' => array(
1195 'id' => 'direct_reward_mode',
1196 'layout' => 'switch',
1197 'checked' => $pool->getOption('direct_reward_mode'),
1198 'value' => $pool->getOption('direct_reward_mode') ? 'on' : '',
1199 'data' => array(
1200 'left' => __("WooCommerce Coupon", 'woorewards-lite'),
1201 'right' => __("Points on Cart", 'woorewards-lite'),
1202 'colorleft' => '#425981',
1203 'colorright' => '#5279b1',
1204 ),
1205 )
1206 ),
1207 array(
1208 'id' => $prefix . 'direct_reward_point_rate',
1209 'type' => 'text',
1210 /* translators: %s: currency symbol */
1211 'title' => sprintf(__("Point Value in %s", 'woorewards-lite'), \LWS\Adminpanel\Tools\Conveniences::isWC() ? \get_woocommerce_currency_symbol() : '?'),
1212 'extra' => array(
1213 'value' => $pool->getOption('direct_reward_point_rate'),
1214 'help' => __("Each point spent on the cart will decrease the order total of that value", 'woorewards-lite')
1215 ),
1216 'require' => array('selector' => '#direct_reward_mode', 'value' => 'on'),
1217 ),
1218 array(
1219 'id' => 'rewards',
1220 'type' => 'editlist',
1221 'title' => __("Coupon", 'woorewards-lite'),
1222 'extra' => array(
1223 'editlist' => \lws_editlist(
1224 'UnlockableList',
1225 \LWS\WOOREWARDS\Ui\Editlists\MultiFormList::ROW_ID,
1226 new \LWS\WOOREWARDS\Ui\Editlists\UnlockableList($pool),
1227 \LWS\Adminpanel\EditList\Modes::MOD
1228 )->setPageDisplay(false)->setCssClass('unlockablelist')->setRepeatHead(false),
1229 ),
1230 'require' => array('selector' => '#direct_reward_mode', 'value' => ''),
1231 ),
1232 )
1233 )
1234 ));
1235
1236 if (\apply_filters('lwsdev_coupon_individual_use_solver_exists', false)) {
1237 $groups['spending']['fields']['discount_cats'] = array(
1238 'id' => $prefix . 'direct_reward_discount_cats',
1239 'title' => __("Exclusive categories", 'woorewards-lite'),
1240 'type' => 'lacchecklist',
1241 'extra' => array(
1242 'comprehensive' => true,
1243 'ajax' => 'lwsdev_coupon_individual_use_solver_categories',
1244 'value' => $pool->getOption('direct_reward_discount_cats'),
1245 'help' => __("Exclusive categories that the coupon will be applied to. Extends the <i>“Individual use only”</i> rule.", 'woorewards-lite'),
1246 ),
1247 'require' => array('selector' => '#direct_reward_mode', 'value' => 'on'),
1248 );
1249 }
1250 }
1251
1252 return $groups;
1253 }
1254
1255 /** For pool option in admin page:
1256 * * be sure field id starts with 'lws-wr-pool-option-' and Pool->setOption accept the id string rest as valid option name.
1257 * * be sure the page contains a <input> named 'pool' with relevant pool id.
1258 * * since field cannot read value in wp get_option, be sure to set the relevant value in extra array.
1259 *
1260 * @param array $fields an array as required by 'fields' entry in admin group.
1261 * @param $pool a Pool instance. */
1262 public function getPoolGeneralSettings($fields, \LWS\WOOREWARDS\Core\Pool $pool)
1263 {
1264 $poolOptionPrefix = 'lws-wr-pool-option-';
1265
1266 $fields['pool'] = array(
1267 'id' => 'lws-wr-pool-option',
1268 'type' => 'hidden',
1269 'extra' => array(
1270 'value' => $pool->getId(),
1271 'id' => 'lws_wr_pool_id',
1272 )
1273 );
1274
1275 $fields['enabled'] = array(
1276 'id' => $poolOptionPrefix . 'enabled', /// id starts with 'lws-wr-pool-option-', 'enabled' is accepted as Pool option
1277 'type' => 'box',
1278 'title' => 'Status',
1279 'extra' => array(
1280 'noconfirm' => true,
1281 'layout' => 'switch',
1282 'checked' => $pool->getOption('enabled'), /// set field value here
1283 'data' => array(
1284 'default' => _x("Off", "pool enabled switch", 'woorewards-lite'),
1285 'checked' => _x("On", "pool enabled switch", 'woorewards-lite')
1286 )
1287 )
1288 );
1289
1290 $fields['title'] = array(
1291 'id' => $poolOptionPrefix . 'title',
1292 'type' => 'text',
1293 'title' => _x("Title", "Pool title", 'woorewards-lite'),
1294 'extra' => array(
1295 'required' => true,
1296 'value' => $pool->getOption('title')
1297 )
1298 );
1299
1300 return $fields;
1301 }
1302
1303 /** Simulate the order status change for order in date range */
1304 function forceOldOrdersTrigger($btnId, $data = array())
1305 {
1306 if ($btnId != 'trigger_orders') return false;
1307
1308 if (!(isset($data['orders_conf']) && \wp_verify_nonce($data['orders_conf'], 'processPastOrders'))) {
1309 /* translators: %s: button label */
1310 $label = __("If you really want to process pre-existing orders, check this box and click on <i>'%s'</i> again.", 'woorewards-lite');
1311 $label = sprintf($label, __("Launch the procedure", 'woorewards-lite'));
1312 $warn = __("If your loyalty program is live, this could lead to lots of rewards being generated and lots of emails being sent", 'woorewards-lite');
1313 $tips = __("Please make sure you reviewed all the settings before launching this procedure.", 'woorewards-lite');
1314
1315 $nonce = \esc_attr(\wp_create_nonce('processPastOrders'));
1316 $str = "<p>"
1317 . "<input type='checkbox' class='lws-ignore-confirm' id='orders_conf' name='orders_conf' value='{$nonce}' autocomplete='off'>"
1318 . "<label for='orders_conf'>{$label} <b style='color: red;'>{$warn}</b><br/>{$tips}</label>"
1319 . "</p>";
1320 return $str;
1321 }
1322
1323 if (!isset($data['date_min']) || !($d1 = \date_create($data['date_min']))) return __("Dates are required", 'woorewards-lite');
1324 if (!isset($data['date_max']) || !($d2 = \date_create($data['date_max']))) return __("Dates are required", 'woorewards-lite');
1325 if ($d2 < $d1) {
1326 $tmp = $d2;
1327 $d2 = $d1;
1328 $d1 = $tmp;
1329 }
1330 $d1 = $d1->format('Y-m-d');
1331 $d2 = $d2->format('Y-m-d');
1332
1333 $status = array_unique(\apply_filters('lws_woorewards_order_events', array('processing', 'completed')));
1334 $status = array_map(function ($s) {
1335 return 'wc-' . $s;
1336 }, $status);
1337
1338 $shopKind = \apply_filters('lws_woorewards_order_backward_apply_shop_kind', array('shop_order'));
1339 $shopKind = implode("','", array_map('\esc_sql', $shopKind));
1340
1341 $args = \apply_filters('lws_woorewards_process_past_orders_query', array(
1342 'limit' => -1,
1343 'type' => $shopKind,
1344 'status' => $status,
1345 'date_created' => $d1 . '...' . $d2,
1346 ));
1347
1348 $count = 0;
1349 foreach ((array)\wc_get_orders($args) as $order) {
1350 \do_action('lws_woorewards_pool_on_order_done', $order->get_id(), $order);
1351 ++$count;
1352 }
1353
1354 /* translators: %s: number of orders */
1355 return sprintf(__("<b>%s</b> order(s) processed.", 'woorewards-lite'), $count);
1356 }
1357
1358 function deleteAllData($btnId, $data = array())
1359 {
1360 if ($btnId != 'trigger_delete_all_woorewards') return false;
1361
1362 if (!(isset($data['del_conf']) && \wp_verify_nonce($data['del_conf'], 'deleteAllData'))) {
1363 /* translators: %s: button label */
1364 $label = __("If you really want to reset all MyRewards data, check this box and click on <i>'%s'</i> again.", 'woorewards-lite');
1365 $label = sprintf($label, __("Delete All Data", 'woorewards-lite'));
1366 $warn = __("This operation is irreversible!", 'woorewards-lite');
1367 $tips = __("Consider making a backup of your database before continue.", 'woorewards-lite');
1368
1369 $nonce = \esc_attr(\wp_create_nonce('deleteAllData'));
1370 $str = "<p>"
1371 . "<input type='checkbox' class='lws-ignore-confirm' id='del_conf' name='del_conf' value='{$nonce}' autocomplete='off'>"
1372 . "<label for='del_conf'>{$label} <b style='color: red;'>{$warn}</b><br/>{$tips}</label>"
1373 . "</p>";
1374 return $str;
1375 }
1376
1377 $wpInstalling = \wp_installing();
1378 \wp_installing(true); // should force no cache
1379 \do_action('lws_woorewards_before_delete_all', $data);
1380 if (defined('WP_DEBUG') && WP_DEBUG) error_log("[MyRewards] Delete everything"); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1381
1382 foreach (array(
1383 'lws_wooreward_max_sponsorship_count',
1384 'lws_woorewards_version',
1385 'lws_woorewards_pointstack_timeout_delete',
1386 ) as $opt) {
1387 \delete_option($opt);
1388 }
1389
1390 global $wpdb;
1391 foreach (array('lws-wre-pool', 'lws-wre-event', 'lws-wre-unlockable') as $post_type) {
1392 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1393 $posts = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type=%s", $post_type));
1394 foreach ($posts as $post_id)
1395 \wp_delete_post($post_id, true);
1396 }
1397
1398 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1399 $wpdb->query("TRUNCATE {$wpdb->base_prefix}lws_wr_historic");
1400 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1401 $wpdb->query("TRUNCATE {$wpdb->prefix}lws_wr_achieved_log");
1402 // do not truncate {$wpdb->base_prefix}lws_wr_tinyurls since such url can be widely shared
1403
1404 // user meta - all keys are hardcoded constants
1405 $ukeys = array(
1406 'lws_wre_unlocked_id',
1407 'lws_wre_pending_achievement',
1408 'lws_wooreward_used_sponsorship',
1409 'lws_woorewards_sponsored_by',
1410 'lws_woorewards_sponsored_origin',
1411 'lws_woorewards_at_registration_sponsorship',
1412 );
1413 $placeholders = \implode(',', \array_fill(0, \count($ukeys), '%s'));
1414 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
1415 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ({$placeholders})", $ukeys));
1416 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1417 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s", 'lws_wr_redeemed_%'));
1418 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1419 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s", 'lws_wre_points_%')); /// @see \LWS\WOOREWARDS\Core\PointStack::MetaPrefix
1420
1421 // post meta
1422 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1423 $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE 'lws_woorewards_%'");
1424 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1425 $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ('reward_origin','reward_origin_id','wre_pool_point_stack')");
1426 // hpos order meta
1427 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1428 if ($wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}wc_orders_meta'")) {
1429 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1430 $wpdb->query("DELETE FROM {$wpdb->prefix}wc_orders_meta WHERE meta_key LIKE 'lws_woorewards_%'");
1431 }
1432
1433 // mails
1434 $prefix = 'lws_mail_' . 'woorewards' . '_attribute_';
1435 \delete_option($prefix . 'headerpic');
1436 \delete_option($prefix . 'footer');
1437 foreach (array('wr_new_reward') as $template) {
1438 \delete_option('lws_mail_subject_' . $template);
1439 \delete_option('lws_mail_preheader_' . $template);
1440 \delete_option('lws_mail_title_' . $template);
1441 \delete_option('lws_mail_header_' . $template);
1442 \delete_option('lws_mail_template_' . $template);
1443 \delete_option('lws_mail_bcc_admin_' . $template);
1444 }
1445
1446 // clean options
1447 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1448 $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'lws_woorewards_%'");
1449 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1450 $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'rflush_lws_woorewards_%'");
1451
1452 \do_action('lws_woorewards_after_delete_all', $data);
1453 \wp_installing($wpInstalling);
1454 return __("You can now create new Points and Rewards System for your customers or uninstall MyRewards.", 'woorewards-lite');
1455 }
1456
1457 public function addSponsorshipTab($page)
1458 {
1459 $current = \LWS\Adminpanel\Tools\Conveniences::getCurrentAdminPage();
1460 if (false === \strpos($current, LWS_WOOREWARDS_PAGE))
1461 return $page;
1462 if (isset($page['tabs']['sponsorship']))
1463 return $page;
1464
1465 $page['tabs']['sponsorship'] = array(
1466 'id' => 'sponsorship',
1467 'title' => __('Referrals', 'woorewards-lite'),
1468 'icon' => 'lws-icon-b-check',
1469 'vertnav'=> true,
1470 'groups' => array(),
1471 );
1472
1473 if ((LWS_WOOREWARDS_PAGE . '.customers') != $current)
1474 return $page;
1475 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab routing
1476 if (!(isset($_REQUEST['tab']) && 'sponsorship' == \sanitize_text_field(\wp_unslash($_REQUEST['tab']))))
1477 return $page;
1478
1479 require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/sponsorships.php';
1480 $page['tabs']['sponsorship']['groups']['sponsors'] = array(
1481 'id' => 'sponsors_list',
1482 'title' => __("Referrals Information", 'woorewards-lite'),
1483 'icon' => 'lws-icon-b-check',
1484 'color' => '#6e96b5',
1485 'text' => array('tag' => 'ul',
1486 __("You will find here a list of all customers who referred other people.", 'woorewards-lite'),
1487 sprintf(
1488 /* translators: %s: shortcode link */
1489 __("See %s to let your customer share a referral link and get referees.", 'woorewards-lite'),
1490 sprintf('<a href="%s">%s</a>',
1491 \esc_attr(\add_query_arg(array(
1492 'page' => LWS_WOOREWARDS_PAGE . '.appearance', 'tab' => 'shortcodes'
1493 ), \admin_url('admin.php#lws_woorewards_referral_link'))),
1494 '[wr_referral_link]'
1495 )
1496 ),
1497 ),
1498 'editlist' => \LWS\WOOREWARDS\Ui\Editlists\Sponsorships::instanciate(),
1499 );
1500
1501 return $page;
1502 }
1503
1504 function restorePointsToDate($btnId, $data = array())
1505 {
1506 if ($btnId != 'trigger_restore_points') return false;
1507
1508 $poolId = isset($data['restore_points_pool']) ? (int)$data['restore_points_pool'] : 0;
1509 if (!$poolId) {
1510 return sprintf('<b style="color: #d76f00;">%s</b>', __("Please select a loyalty system", 'woorewards-lite'));
1511 }
1512
1513 $targetDate = isset($data['restore_points_date']) ? \sanitize_text_field(\trim($data['restore_points_date'])) : '';
1514 if (!$targetDate) {
1515 return sprintf('<b style="color: #d76f00;">%s</b>', __("Please select a date", 'woorewards-lite'));
1516 }
1517
1518 if (!(isset($data['restore_conf']) && \wp_verify_nonce($data['restore_conf'], 'restorePointsToDate'))) {
1519 /* translators: %s: button label */
1520 $label = __("If you really want to restore points, check this box and click on <i>'%s'</i> again.", 'woorewards-lite');
1521 $label = sprintf($label, __("Restore Points", 'woorewards-lite'));
1522 $warn = __("This will adjust all users' points in the selected system.", 'woorewards-lite');
1523
1524 $nonce = \esc_attr(\wp_create_nonce('restorePointsToDate'));
1525 $str = "<p>"
1526 . "<input type='checkbox' class='lws-ignore-confirm' id='restore_conf' name='restore_conf' value='{$nonce}' autocomplete='off'>"
1527 . "<label for='restore_conf'>{$label} <b style='color: #d76f00;'>{$warn}</b></label>"
1528 . "</p>";
1529 return $str;
1530 }
1531
1532 $targetTime = isset($data['restore_points_time']) ? \sanitize_text_field(\trim($data['restore_points_time'])) : '23:59';
1533 if (!$targetTime) {
1534 $targetTime = '23:59';
1535 }
1536
1537 $timeParts = explode(':', $targetTime);
1538 if (count($timeParts) < 2 || !is_numeric($timeParts[0]) || !is_numeric($timeParts[1])) {
1539 return sprintf('<b style="color: #d76f00;">%s</b>', __("Invalid time format", 'woorewards-lite'));
1540 }
1541
1542 $hour = (int)$timeParts[0];
1543 $minute = (int)$timeParts[1];
1544 $second = isset($timeParts[2]) && is_numeric($timeParts[2]) ? (int)$timeParts[2] : 59;
1545
1546 if ($hour < 0 || $hour > 23 || $minute < 0 || $minute > 59 || $second < 0 || $second > 59) {
1547 return sprintf('<b style="color: #d76f00;">%s</b>', __("Invalid time values", 'woorewards-lite'));
1548 }
1549
1550 $localTimezone = \wp_timezone();
1551 $dateObj = \date_create($targetDate, $localTimezone);
1552 if (!$dateObj) {
1553 return sprintf('<b style="color: #d76f00;">%s</b>', __("Invalid date format", 'woorewards-lite'));
1554 }
1555
1556 $dateObj->setTime($hour, $minute, $second);
1557
1558 $now = new \DateTime('now', $localTimezone);
1559 if ($dateObj > $now) {
1560 return sprintf('<b style="color: #d76f00;">%s</b>', __("Cannot restore to a future date", 'woorewards-lite'));
1561 }
1562
1563 $targetDateDisplay = $dateObj->format(\get_option('date_format') . ' ' . \get_option('time_format'));
1564
1565 $dateObj->setTimezone(new \DateTimeZone('GMT'));
1566 $targetDateFormatted = $dateObj->format('Y-m-d H:i:s');
1567
1568 if (\class_exists('\LWS\WOOREWARDS\PRO\Core\Pool')) {
1569 $pool = \LWS\WOOREWARDS\PRO\Core\Pool::getOrLoad($poolId, false);
1570 } else {
1571 $pool = \apply_filters('lws_woorewards_get_pools_by_args', false, array(
1572 'post_id' => $poolId,
1573 'force' => true,
1574 ));
1575 if ($pool) $pool = $pool->first();
1576 }
1577
1578 if (!$pool) {
1579 return sprintf('<b style="color: #d76f00;">%s</b>', __("The selected loyalty system can't be found", 'woorewards-lite'));
1580 }
1581
1582 $stackId = $pool->getStackId();
1583 $poolName = $pool->getOption('display_title');
1584 if (!$poolName) {
1585 $poolName = $pool->getOption('title', __("Loyalty System", 'woorewards-lite'));
1586 }
1587
1588 try {
1589 global $wpdb;
1590 $blogId = \get_current_blog_id();
1591
1592 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1593 $historicalBalances = $wpdb->get_results($wpdb->prepare("
1594 SELECT
1595 h.user_id,
1596 h.new_total as historical_balance
1597 FROM {$wpdb->lwsWooRewardsHistoric} h
1598 INNER JOIN (
1599 SELECT user_id, MAX(id) as max_id
1600 FROM {$wpdb->lwsWooRewardsHistoric}
1601 WHERE stack = %s
1602 AND mvt_date <= %s
1603 AND blog_id = %d
1604 GROUP BY user_id
1605 ) latest ON h.user_id = latest.user_id AND h.id = latest.max_id
1606 ", $stackId, $targetDateFormatted, $blogId), ARRAY_A);
1607
1608 $metaKey = \LWS\WOOREWARDS\Core\PointStack::MetaPrefix . $stackId;
1609 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1610 $currentHolders = $wpdb->get_results($wpdb->prepare("
1611 SELECT user_id, CAST(meta_value AS SIGNED) as current_points
1612 FROM {$wpdb->usermeta}
1613 WHERE meta_key = %s
1614 AND meta_value != ''
1615 ", $metaKey), ARRAY_A);
1616
1617 $historicalMap = array();
1618 foreach ($historicalBalances as $row) {
1619 $historicalMap[(int)$row['user_id']] = (int)$row['historical_balance'];
1620 }
1621
1622 \set_time_limit(0); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- long running admin operation
1623
1624 /* translators: %s: target date */
1625 $reason = sprintf(__("Points restored to %s", 'woorewards-lite'), $targetDateDisplay);
1626
1627 $adjusted = 0;
1628 $unchanged = 0;
1629 $resetToZero = 0;
1630
1631 foreach ($currentHolders as $holder) {
1632 $userId = (int)$holder['user_id'];
1633 $currentPoints = (int)$holder['current_points'];
1634
1635 $targetBalance = isset($historicalMap[$userId]) ? $historicalMap[$userId] : 0;
1636
1637 if ($currentPoints === $targetBalance) {
1638 $unchanged++;
1639 continue;
1640 }
1641
1642 $stack = new \LWS\WOOREWARDS\Core\PointStack($stackId, $userId);
1643 $stack->set($targetBalance, $reason, 'restore_to_date', $poolId);
1644
1645 if ($targetBalance === 0) {
1646 $resetToZero++;
1647 } else {
1648 $adjusted++;
1649 }
1650 }
1651
1652 /* translators: %1$s: system name, %2$s: target date */
1653 $message = sprintf(__('Points restoration completed for system <b>%1$s</b> to date <b>%2$s</b>:', 'woorewards-lite'), \esc_html($poolName), $targetDateDisplay);
1654
1655 $stats = array();
1656 if ($adjusted > 0) {
1657 /* translators: %d: number of users */
1658 $stats[] = sprintf(__("%d user(s) adjusted", 'woorewards-lite'), $adjusted);
1659 }
1660 if ($resetToZero > 0) {
1661 /* translators: %d: number of users */
1662 $stats[] = sprintf(__("%d user(s) reset to zero", 'woorewards-lite'), $resetToZero);
1663 }
1664 if ($unchanged > 0) {
1665 /* translators: %d: number of users */
1666 $stats[] = sprintf(__("%d user(s) unchanged", 'woorewards-lite'), $unchanged);
1667 }
1668
1669 if (empty($stats)) {
1670 $stats[] = __("No users affected", 'woorewards-lite');
1671 }
1672
1673 return '<div style="color: #155724; background-color: #d4edda; border: 1px solid #c3e6cb; padding: 12px; border-radius: 4px; margin: 10px 0;">'
1674 . $message . '<ul style="margin: 8px 0 0 20px;"><li>' . implode('</li><li>', $stats) . '</li></ul>'
1675 . '</div>';
1676
1677 } catch (\Exception $e) {
1678 if (defined('WP_DEBUG') && WP_DEBUG) {
1679 \error_log('WooRewards Point Restore Error: ' . $e->getMessage()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1680 \error_log('Stack trace: ' . $e->getTraceAsString()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
1681 }
1682
1683 return sprintf(
1684 '<b style="color: red;">%s</b><p><i>%s</i></p>',
1685 __("An error occurred during point restoration", 'woorewards-lite'),
1686 \esc_html($e->getMessage())
1687 );
1688 }
1689 }
1690 }