managePages());
\add_action('admin_enqueue_scripts', array($this, 'scripts'));
// replace usual notice by a badge teaser
if (!defined('LWS_WOOREWARDS_ACTIVATED') || !LWS_WOOREWARDS_ACTIVATED)
\add_filter('pre_set_transient_settings_errors', array($this, 'noticeSettingsSaved'));
$this->checkCouponsEnabled();
}
protected function getCurrentPage()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- page routing only
if (isset($_REQUEST['page']) && ($current = \sanitize_text_field(\wp_unslash($_REQUEST['page']))))
return $current;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- page routing only
if (isset($_REQUEST['option_page']) && ($current = \sanitize_text_field(\wp_unslash($_REQUEST['option_page']))))
return $current;
return false;
}
protected function checkCouponsEnabled()
{
if (defined('DOING_AJAX') && DOING_AJAX)
return;
if (function_exists('\wc_coupons_enabled') && !\wc_coupons_enabled() && !\get_option('lws_woorewards_ignore_woocommerce_disable_coupons')) {
$ignore = false;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- admin notice dismissal
if (isset($_GET['lws_wr_wc_coupons_enable']) && in_array(\sanitize_text_field(\wp_unslash($_GET['lws_wr_wc_coupons_enable'])), array('yes', 'ignore'))) {
if (\current_user_can('manage_options')) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( \sanitize_text_field( \wp_unslash( $_GET['lws_wr_wc_coupons_enable'] ) ) == 'yes' ) {
\update_option( 'woocommerce_enable_coupons', 'yes' );
\update_option( 'lws_woorewards_ignore_woocommerce_disable_coupons', '' );
} else {
\update_option( 'lws_woorewards_ignore_woocommerce_disable_coupons', 'yes' );
}
}
$ignore = true;
}
if (!$ignore) {
$message = array();
$message[] = __("WooCommerce Coupons are disabled. Several MyRewards features will be broken without Coupons.", 'woorewards-lite');
$message[] = __("You can check your WooCommerce General Settings and look for : Enable coupons.", 'woorewards-lite');
if (\current_user_can('manage_options')) {
$message[] = sprintf(
/* translators: %1$s: link to resolve, %2$s: link to ignore */
__( '%1$s or %2$s this warning at your own risks.', 'woorewards-lite' ),
sprintf(
"%s",
\esc_attr( \add_query_arg( 'lws_wr_wc_coupons_enable', 'yes' ) ),
__( "Click here to resolve the problem immediately", 'woorewards-lite' )
),
sprintf(
"%s",
\esc_attr( \add_query_arg( 'lws_wr_wc_coupons_enable', 'ignore' ) ),
__( "ignore", 'woorewards-lite' )
)
);
}
\lws_admin_add_notice_once('woocommerce_enable_coupons', implode('
', $message), array('level' => 'error'));
}
}
}
public function scripts($hook)
{
// Force the menu icon with lws-icons font
\wp_enqueue_style('wr-menu-icon', LWS_WOOREWARDS_CSS . '/menu-icon.css', array(), LWS_WOOREWARDS_VERSION);
\wp_register_script('lws_wre_system_selector', LWS_WOOREWARDS_JS . '/poolsettings.js', array('lws-base64'), LWS_WOOREWARDS_VERSION, true);
\wp_register_style('lws_wre_system_selector', LWS_WOOREWARDS_CSS . '/poolsettings.css', array(), LWS_WOOREWARDS_VERSION);
if (false !== ($ppos = strpos($hook, LWS_WOOREWARDS_PAGE))) {
$page = substr($hook, $ppos);
$tab = isset($_GET['tab']) ? \sanitize_text_field(\wp_unslash($_GET['tab'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab routing
if (!defined('LWS_WOOREWARDS_ACTIVATED') || !LWS_WOOREWARDS_ACTIVATED) {
// let badge teaser replace the notice
\wp_enqueue_style('lws-wre-notice', LWS_WOOREWARDS_CSS . '/notice.css', array(), LWS_WOOREWARDS_VERSION);
}
if ($page == LWS_WOOREWARDS_PAGE || false !== strpos($page, 'customers')) {
// labels displayed in points history
$labels = array(
'hist' => __("Points History", 'woorewards-lite'),
'desc' => __("Description", 'woorewards-lite'),
'date' => __("Date", 'woorewards-lite'),
'points' => __("Points", 'woorewards-lite'),
'total' => __("Total", 'woorewards-lite'),
);
// enqueue editlist column folding script
foreach (($deps = array('jquery', 'lws-tools')) as $dep)
\wp_enqueue_script($dep);
\wp_register_script('lws-wre-userspoints', LWS_WOOREWARDS_JS . '/userspoints.js', $deps, LWS_WOOREWARDS_VERSION, true);
\wp_localize_script('lws-wre-userspoints', 'lws_wr_userspoints_labels', $labels);
\wp_enqueue_script('lws-wre-userspoints');
\wp_enqueue_style('lws-wre-userspoints', LWS_WOOREWARDS_CSS . '/userspoints.css', array(), LWS_WOOREWARDS_VERSION);
\do_action('lws_adminpanel_enqueue_lac_scripts', array('select'));
\do_action('lws_woorewards_ui_userspoints_enqueue_scripts', $hook, $tab);
} else if (false !== strpos($page, 'loyalty')) {
\do_action('lws_adminpanel_enqueue_lac_scripts', array('select'));
} else if (false !== strpos($page, 'appearance')) {
\wp_enqueue_style('lws_wr_pointsoncart_hard', LWS_WOOREWARDS_CSS . '/pointsoncart.css', array(), LWS_WOOREWARDS_VERSION);
}
\wp_enqueue_script('lws-wre-coupon-edit', LWS_WOOREWARDS_JS . '/couponedit.js', array('jquery'), LWS_WOOREWARDS_VERSION, true);
}
}
/** Push an achievement teaser instead our usual notice at setting save. */
public function noticeSettingsSaved($value)
{
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WP settings API handles nonce
if (!empty($value) && isset($_POST['option_page']) && false !== strpos(\sanitize_text_field(\wp_unslash($_POST['option_page'])), LWS_WOOREWARDS_PAGE)) {
$val = \current($value);
if (isset($val['type']) && $val['type'] == 'updated' && isset($val['code']) && $val['code'] == 'settings_updated') {
$teasers = array(
__("Add fun and achievements for your customers with the Pro Version", 'woorewards-lite'),
__("Try the Pro Version for free for 30 days", 'woorewards-lite'),
__("The Pro Version adds Events and Levelling systems. Try it", 'woorewards-lite')
);
\LWS_WooRewards::achievement(array(
'title' => __("Your settings have been saved.", 'woorewards-lite'),
'message' => str_replace(
'',
"",
$teasers[wp_rand(0, count($teasers) - 1)]
)
));
}
}
return $value;
}
protected function managePages()
{
$pages = array();
$pages['wr_resume'] = $this->getResumePage();
$pages['wr_customers'] = $this->getCustomerPage();
if (false === ($pages['wr_settings'] = \apply_filters('lws_woorewards_ui_settings_page_get', false))) {
$pages['wr_settings'] = $this->getSettingsPage();
}
if (defined('LWS_WIZARD_SUMMONER')) {
$pages['wr_wizard'] = $this->getWizardPage();
}
//$pages['wr_features'] = $this->getFeaturesPage();
$pages['wr_appearance'] = $this->getAppearancePage();
$pages['wr_system'] = $this->getSystemPage();
if (!\apply_filters('lws-ap-release-woorewards', ''))
$pages['wr_proversion'] = $this->getProVersionPage();
return $pages;
}
protected function getResumePage()
{
$resumePage = array(
'title' => __("MyRewards", 'woorewards-lite'),
'id' => LWS_WOOREWARDS_PAGE,
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'dashicons' => '',
'index' => 57,
'resume' => true,
'tabs' => array(
'wr_customers' => array(
'title' => __("Customers", 'woorewards-lite'),
'id' => 'resume_customers',
)
)
);
return $resumePage;
}
protected function getCustomerPage()
{
require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/userspoints.php';
require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/userspointsbulkaction.php';
$editlist = \lws_editlist(
'userspoints',
'user_id',
new \LWS\WOOREWARDS\Ui\Editlists\UsersPoints(),
\LWS\Adminpanel\EditList\Modes::FIX,
\apply_filters('lws_woorewards_admin_userspoints_filters', array(
'user_search' => new \LWS\Adminpanel\EditList\FilterSimpleField('usersearch', __('Search...', 'woorewards-lite')),
'points_add' => new \LWS\WOOREWARDS\Ui\Editlists\UsersPointsBulkAction('points_add')
))
);
$cusPage = array(
'title' => __("Customers", 'woorewards-lite'),
'id' => LWS_WOOREWARDS_PAGE . '.customers',
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'color' => '#A8CE38',
'image' => LWS_WOOREWARDS_IMG . '/r-customers.png',
'description' => __("Use this page to manage your customers, see and edit their points and rewards", 'woorewards-lite'),
'tabs' => array(
'wr_customers' => array(
'title' => __("Customers", 'woorewards-lite'),
'id' => 'wr_customers',
'icon' => 'lws-icon-users-wm',
'groups' => array(
'customers_points' => array(
'title' => __("Points Management", 'woorewards-lite'),
'icon' => 'lws-icon-users',
'color' => '#00768b',
'text' => __("Here you can see and manage your customers reward points", 'woorewards-lite')
. "
" . __("You can view the points history by clicking the points total in the table", 'woorewards-lite'),
'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('customers')),
'editlist' => $editlist,
)
)
)
)
);
return $cusPage;
}
protected function getSettingsPage()
{
return array(
'title' => __("Settings", 'woorewards-lite'),
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'id' => LWS_WOOREWARDS_PAGE . '.loyalty',
'color' => '#526981',
'image' => LWS_WOOREWARDS_IMG . '/r-loyalty-systems.png',
'description' => __("Use this page to manage your loyalty program, see and edit actions and rewards", 'woorewards-lite'),
'tabs' => array(
'wr_loyalty' => array(
'title' => __("Points and Rewards", 'woorewards-lite'),
'id' => 'wr_loyalty',
'icon' => 'lws-icon-present',
'groups' => $this->getLoyaltyGroups()
),
'wr_othersettings' => array(
'title' => __("Other Settings", 'woorewards-lite'),
'id' => 'wr_othersettings',
'icon' => 'lws-icon-adv-settings',
'groups' => $this->getSettingsGroups()
)
)
);
}
protected function getWizardPage()
{
return array(
'title' => __("Wizard", 'woorewards-lite'),
'subtitle' => __("Wizard", 'woorewards-lite'),
'id' => LWS_WIZARD_SUMMONER . LWS_WOOREWARDS_PAGE,
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'color' => '#00B7EB',
'image' => LWS_WOOREWARDS_IMG . '/r-wizard.png',
'description' => __("The wizard page lets you setup your points and rewards program in a few minutes", 'woorewards-lite'),
);
}
protected function getSettingsGroups()
{
return array(
'settings' => array(
'id' => 'settings',
'icon' => 'lws-icon-settings-gear',
'title' => __("General settings", 'woorewards-lite'),
'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'),
'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('adv-features')),
'fields' => array(
'inc_taxes' => array(
'id' => 'lws_woorewards_order_amount_includes_taxes',
'title' => __("Includes taxes", 'woorewards-lite'),
'type' => 'box',
'extra' => array(
'layout' => 'toggle',
'help' => __("If checked, taxes will be included in the points earned when spending money", 'woorewards-lite'),
)
),
'c_prefix' => array(
'id' => 'lws_woorewards_reward_coupon_code_prefix',
'title' => __("Coupon prefix", 'woorewards-lite'),
'type' => 'text',
'extra' => array(
'size' => '10',
'help' => __("Set a prefix code that will be added on all coupon codes generated by MyRewards", 'woorewards-lite'),
)
),
'c_length' => array(
'id' => 'lws_woorewards_coupon_code_length',
'title' => __("Coupon code length", 'woorewards-lite'),
'type' => 'text',
'extra' => array(
'size' => '3',
'default' => '10',
'placeholder' => '10',
'help' => __("Set the length of the generated coupon code. The length comes in addition to the code prefix.", 'woorewards-lite')
/* translators: %s: minimum code length */
. ' ' . sprintf(__("Minimum length is %s.", 'woorewards-lite'), \LWS\WOOREWARDS\Unlockables\Coupon::COUPON_CODE_MIN_LENGTH),
)
),
'order_state' => array(
'id' => 'lws_woorewards_points_distribution_status',
'title' => __("Order statuses for points", 'woorewards-lite'),
'type' => 'lacchecklist',
'extra' => array(
'ajax' => 'lws_adminpanel_get_order_status',
'help' => __("Default state to get points is the processing order status.
If you want to use other statuses instead (recommanded), select them here", 'woorewards-lite'),
)
),
'deep_usersearch' => array(
'id' => 'lws_woorewards_admin_userspoints_deep_search',
'title' => __("Deep customer search", 'woorewards-lite'),
'type' => 'box',
'extra' => array(
'layout' => 'toggle',
'default' => 'on',
'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'),
)
),
'show_priorities' => array(
'id' => 'lws_woorewards_show_loading_order_and_priority',
'title' => __("Show loading orders", 'woorewards-lite'),
'type' => 'box',
'extra' => array(
'layout' => 'toggle',
'help' => __("For some advanced setups, managing loyalty system loading order and event trigger priority could be meaningful.", 'woorewards-lite'),
)
),
)
),
'pointsoncart' => array(
'id' => 'pointsoncart',
'icon' => 'lws-icon-coins',
'title' => __("Order statuses to consume used points", 'woorewards-lite'),
'text' => __("Points used to get a discount are consumed when order status changes.", 'woorewards-lite'),
'fields' => array(
'order_state' => array(
'id' => 'lws_woorewards_pointdiscount_pay_order_status',
'title' => __("Order statuses to pay discount", 'woorewards-lite'),
'type' => 'lacchecklist',
'extra' => array(
'ajax' => 'lws_adminpanel_get_order_status',
'default' => array('processing', 'completed'),
)
),
'failure' => array(
'id' => 'lws_woorewards_pointdiscount_pay_order_failure',
'title' => __("Order status on payment failure", 'woorewards-lite'),
'type' => 'lacselect',
'extra' => array(
'mode' => 'select',
'source' => array(
array('value' => '_', 'label' => __("[do nothing]", 'woorewards-lite'))
),
'ajax' => 'lws_adminpanel_get_order_status',
'default' => 'failed',
'help' => __("Change order status if points cannot be paid after all.", 'woorewards-lite'),
)
),
)
),
'sponsorship' => array(
'id' => 'sponsorship',
'icon' => 'lws-icon-handshake',
'color' => '#669876',
'title' => __("Referral Features", 'woorewards-lite'),
'text' => __("Here, you'll find the different tools customers can use to refer their friends and the reward given to referred users.", 'woorewards-lite') .
__("To reward the referrers, either use the dedicated wizard or select an appropriate earning method inside a points and rewards system.", 'woorewards-lite'),
'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('referral')),
'fields' => array(
'enable' => array(
'id' => 'lws_woorewards_event_enabled_sponsorship',
'title' => __("Enable Referrals", 'woorewards-lite'),
'type' => 'box',
'extra' => array(
'layout' => 'toggle',
'default' => 'on'
)
),
'enableReferral' => array(
'id' => 'lws_woorewards_referral_back_give_sponsorship',
'type' => 'box',
'title' => __("Allow referrals via referral link", 'woorewards-lite'),
'extra' => array(
'default' => 'on',
'layout' => 'toggle',
'help' => __("When a visitor comes from a referral link and registers, he will be referred by the user that posted the link.", 'woorewards-lite')
)
),
'tinify' => array(
'id' => 'lws_woorewards_sponsorship_tinify_enabled',
'title' => __("Try to shorten the referral URL", 'woorewards-lite'),
'type' => 'box',
'extra' => array(
'help' => __('Disable that feature if you encounter plugin conflicts or redirection problems. Disable that feature makes bigger and less readable QR codes.', 'woorewards-lite'),
'class' => 'lws_checkbox',
'default' => '',
'id' => 'lws_woorewards_sponsorship_tinify_enabled',
)
),
'tiny' => array(
'id' => 'lws_woorewards_sponsorship_short_url',
'title' => __("Alternative Short Site URL", 'woorewards-lite'),
'type' => 'text',
'extra' => array(
'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'),
'placeholder' => \site_url(),
),
'require' => array('selector' => '#lws_woorewards_sponsorship_tinify_enabled', 'value' => 'on'),
),
'max' => array(
'id' => 'lws_wooreward_max_sponsorship_count',
'title' => __("Max referrals per customer", 'woorewards-lite'),
'type' => 'text',
'extra' => array(
'pattern' => '\d+',
'default' => '0',
'help' => __("Set the maximum referrals allowed for users. No restriction on empty value or zero (0).", 'woorewards-lite')
)
),
)
),
);
}
protected function getAppearancePage()
{
require_once LWS_WOOREWARDS_INCLUDES . '/ui/adminscreens/styling.php';
$appearancePage = array(
'title' => __("Appearance", 'woorewards-lite'),
'subtitle' => __("Appearance", 'woorewards-lite'),
'id' => LWS_WOOREWARDS_PAGE . '.appearance',
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'color' => '#4CBB41',
'image' => LWS_WOOREWARDS_IMG . '/r-appearance.png',
'description' => __("Use this page to display loyalty content to your customers on your website", 'woorewards-lite'),
'tabs' => array(
'woocommerce' => $this->getWoocommerceTab(),
'shortcodes' => $this->getShortcodesTab(),
'sty_mails' => array(
'id' => 'sty_mails',
'title' => __("Emails", 'woorewards-lite'),
'icon' => 'lws-icon-letter',
'groups' => \lws_mail_settings(\apply_filters('lws_woorewards_mails', array()))
),
'styling' => \LWS\WOOREWARDS\Ui\AdminScreens\Styling::getTab(true)
)
);
if (\LWS\WOOREWARDS\Conveniences::instance()->isLegacyShown('4.7.0')) {
$appearancePage['tabs']['legacy'] = $this->getLegacyTab();
}
return $appearancePage;
}
protected function getSystemPage()
{
$systemPage = array(
'title' => __("System", 'woorewards-lite'),
'subtitle' => __("System", 'woorewards-lite'),
'id' => LWS_WOOREWARDS_PAGE . '.system',
'rights' => \LWS\Adminpanel\Tools\Conveniences::getCapOnRole('manage_rewards'),
'color' => '#7958A5',
'image' => LWS_WOOREWARDS_IMG . '/r-system.png',
'description' => __("Export or import your customers points, process past orders in this page", 'woorewards-lite'),
'delayedFunction' => array($this, 'showCronStatus'),
'tabs' => array(
'data_management' => array(
'id' => 'data_management',
'title' => __("Data Management", 'woorewards-lite'),
'icon' => 'lws-icon-components',
'groups' => array(
'wc_old_orders' => array(
'id' => 'wc_old_orders',
'icon' => 'lws-icon-repeat',
'title' => __("Give Points for Past orders", 'woorewards-lite'),
'text' => __("If you want to give points for orders that pre-existed your loyalty system, you can do it here", 'woorewards-lite') . '
',
'fields' => array(),
'extra' => array('doclink' => \LWS\WOOREWARDS\DocLinks::get('past-orders'))
),
)
),
)
);
$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');
if (\LWS\Adminpanel\Tools\Conveniences::isHPOS())
$url = \add_query_arg('page', 'wc-orders', \admin_url('admin.php'));
else
$url = \add_query_arg('post_type', 'shop_order', \admin_url('edit.php'));
$systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['link'] = array(
'id' => 'redirect_to_order_bulk',
'title' => '',
'type' => 'custom',
'extra' => array(
'gizmo' => true,
'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(array(
'tag' => 'ul',
sprintf('%s', __("If your loyalty program is live, this could lead to lots of rewards being generated and lots of emails being sent", 'woorewards-lite')),
sprintf('%s', __("Please make sure you reviewed all the settings before launching this procedure.", 'woorewards-lite')),
sprintf('%s', __("Please ensure you agree to send emails to your customers about there activities in loyalty systems or deactivate relevant emails first.", 'woorewards-lite')),
sprintf('%s', \esc_attr(\add_query_arg(array(
'page' => LWS_WOOREWARDS_PAGE . '.appearance',
'tab' => 'sty_mails',
), \admin_url('admin.php'))), __("See WooRewards emails settings", 'woorewards-lite')),
), array(
/* translators: %s: URL to WooCommerce Orders */
sprintf(__("Go to the WooCommerce Orders list.", 'woorewards-lite'), \esc_attr($url)),
__("Check the box at left of the orders to process.", 'woorewards-lite'),
/* translators: %s: bulk action label */
sprintf(__("In the Bulk Actions drop-list, pick %s.", 'woorewards-lite'), \LWS\WOOREWARDS\Ui\Woocommerce\OrdersBulk::getLabel()),
__("Then, press the Apply button.", 'woorewards-lite'),
))),
)
);
//if ((isset($_GET['legacy']) && 'yes' === $_GET['legacy']) || (isset($_POST['button']) && 'trigger_orders' === $_POST['button'])) {
//$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');
$systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['separator'] = array(
'id' => 'past_order_per_date_separator',
'title' => '',
'type' => 'custom',
'extra' => array(
'gizmo' => true,
'separator' => true,
'content' => \LWS\Adminpanel\Tools\Conveniences::array2html(array(
__("Or use our date range selector", 'woorewards-lite'),
array('tag' => 'small',
__("(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'),
),
)),
)
);
$systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['per_dates'] = array(
'id' => 'past_order_per_date_range',
'title' => __("Date range", 'woorewards-lite'),
'type' => 'custom',
'extra' => array(
'gizmo' => true,
'content' => function(){
return sprintf(
"From %s to %s",
\LWS\Adminpanel\Pages\Field\Input::compose('date_min', array(
'type' => 'date',
'gizmo' => true,
'class' => 'lws-ignore-confirm',
'default' => \date_create()->sub(new \DateInterval('P1M'))->format('Y-m-d'),
)), \LWS\Adminpanel\Pages\Field\Input::compose('date_max', array(
'type' => 'date',
'gizmo' => true,
'class' => 'lws-ignore-confirm',
'default' => \gmdate('Y-m-d'),
))
);
},
)
);
$systemPage['tabs']['data_management']['groups']['wc_old_orders']['fields']['trigger_orders'] = array(
'id' => 'trigger_orders',
'title' => __("Launch the procedure", 'woorewards-lite'),
'type' => 'button',
'extra' => array(
'callback' => array($this, 'forceOldOrdersTrigger')
),
);
//}
require_once LWS_WOOREWARDS_INCLUDES . '/ui/adminscreens/pointsmanagement.php';
\LWS\WOOREWARDS\Ui\AdminScreens\PointsManagement::mergeGroups($systemPage['tabs']['data_management']['groups']);
$systemPage['tabs']['data_management']['groups']['restore_points'] = array(
'id' => 'restore_points',
'title' => __("Restore Points to Historical Date", 'woorewards-lite'),
'icon' => 'lws-icon-time-machine',
'class' => 'half',
'text' => __("Rollback all users' point balances to their state on a specific date.", 'woorewards-lite')
. '
' . __("This analyzes the history table and adjusts current balances accordingly.", 'woorewards-lite')
. '
' . __("Note: New history entries will be created showing the adjustment.", 'woorewards-lite') . '',
'fields' => array(
'restore_pool' => array(
'id' => 'restore_points_pool',
'title' => __("Select points and rewards system", 'woorewards-lite'),
'type' => 'lacselect',
'extra' => array(
'gizmo' => true,
'class' => 'lws-ignore-confirm',
'ajax' => 'lws_woorewards_pool_list',
'required' => true,
'help' => __("Select the loyalty system to restore. Only one system can be restored at a time.", 'woorewards-lite'),
),
),
'restore_date' => array(
'id' => 'restore_points_date',
'title' => __("Restore to date", 'woorewards-lite'),
'type' => 'input',
'extra' => array(
'gizmo' => true,
'type' => 'date',
'class' => 'lws-ignore-confirm',
'required' => true,
'max' => \gmdate('Y-m-d'),
'help' => __("Select the target date for restoration.", 'woorewards-lite'),
),
),
'restore_time' => array(
'id' => 'restore_points_time',
'title' => __("Restore to time", 'woorewards-lite'),
'type' => 'input',
'extra' => array(
'gizmo' => true,
'type' => 'time',
'class' => 'lws-ignore-confirm',
'value' => '23:59',
'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'),
),
),
'trigger_restore' => array(
'id' => 'trigger_restore_points',
'title' => __("Restore Points", 'woorewards-lite'),
'type' => 'button',
'extra' => array(
'gizmo' => true,
'callback' => array($this, 'restorePointsToDate')
),
),
)
);
$systemPage['tabs']['data_management']['groups']['delete'] = array(
'id' => 'delete',
'title' => __("Delete all data", 'woorewards-lite'),
'icon' => 'lws-icon-delete-forever',
'class' => 'half',
'text' => __("Remove all loyalty systems, user points and all MyRewards related data.", 'woorewards-lite')
. '
' . __("Use this feature with care since this action is irreversible.", 'woorewards-lite'),
'fields' => array(
'trigger_delete' => array(
'id' => 'trigger_delete_all_woorewards',
'title' => __("Delete All Data", 'woorewards-lite'),
'type' => 'button',
'extra' => array(
'callback' => array($this, 'deleteAllData')
),
),
)
);
return $systemPage;
}
function showCronStatus()
{
$text = array();
if ($next = \intval(\wp_next_scheduled('lws_woorewards_daily_event'))) {
$d = \date_create('now', \LWS_WooRewards::getSiteTimezone())->setTimestamp($next);
/* translators: %1$s: date and time, %2$s: UTC offset */
$text[] = sprintf(__('Next CRON action planned at %1$s (UTC%2$s).', 'woorewards-lite'), $d->format('Y-m-d H:i'), $d->format('P'));
} else {
$text[] = __('CRON action is not registered. To fix it, deactivate then re-activate this plugin.', 'woorewards-lite');
}
if ($last = \intval(\get_option('lws_woorewards_last_cron_time'))) {
$d = \date_create('now', \LWS_WooRewards::getSiteTimezone())->setTimestamp($last);
/* translators: %1$s: date and time, %2$s: UTC offset */
$text[] = sprintf(__('Last CRON action ran at %1$s (UTC%2$s).', 'woorewards-lite'), $d->format('Y-m-d H:i'), $d->format('P'));
}
$text = implode('
', $text);
echo wp_kses_post("
%s
%s
%s
" . "" . "" . "
"; return $str; } if (!isset($data['date_min']) || !($d1 = \date_create($data['date_min']))) return __("Dates are required", 'woorewards-lite'); if (!isset($data['date_max']) || !($d2 = \date_create($data['date_max']))) return __("Dates are required", 'woorewards-lite'); if ($d2 < $d1) { $tmp = $d2; $d2 = $d1; $d1 = $tmp; } $d1 = $d1->format('Y-m-d'); $d2 = $d2->format('Y-m-d'); $status = array_unique(\apply_filters('lws_woorewards_order_events', array('processing', 'completed'))); $status = array_map(function ($s) { return 'wc-' . $s; }, $status); $shopKind = \apply_filters('lws_woorewards_order_backward_apply_shop_kind', array('shop_order')); $shopKind = implode("','", array_map('\esc_sql', $shopKind)); $args = \apply_filters('lws_woorewards_process_past_orders_query', array( 'limit' => -1, 'type' => $shopKind, 'status' => $status, 'date_created' => $d1 . '...' . $d2, )); $count = 0; foreach ((array)\wc_get_orders($args) as $order) { \do_action('lws_woorewards_pool_on_order_done', $order->get_id(), $order); ++$count; } /* translators: %s: number of orders */ return sprintf(__("%s order(s) processed.", 'woorewards-lite'), $count); } function deleteAllData($btnId, $data = array()) { if ($btnId != 'trigger_delete_all_woorewards') return false; if (!(isset($data['del_conf']) && \wp_verify_nonce($data['del_conf'], 'deleteAllData'))) { /* translators: %s: button label */ $label = __("If you really want to reset all MyRewards data, check this box and click on '%s' again.", 'woorewards-lite'); $label = sprintf($label, __("Delete All Data", 'woorewards-lite')); $warn = __("This operation is irreversible!", 'woorewards-lite'); $tips = __("Consider making a backup of your database before continue.", 'woorewards-lite'); $nonce = \esc_attr(\wp_create_nonce('deleteAllData')); $str = "" . "" . "" . "
"; return $str; } $wpInstalling = \wp_installing(); \wp_installing(true); // should force no cache \do_action('lws_woorewards_before_delete_all', $data); if (defined('WP_DEBUG') && WP_DEBUG) error_log("[MyRewards] Delete everything"); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log foreach (array( 'lws_wooreward_max_sponsorship_count', 'lws_woorewards_version', 'lws_woorewards_pointstack_timeout_delete', ) as $opt) { \delete_option($opt); } global $wpdb; foreach (array('lws-wre-pool', 'lws-wre-event', 'lws-wre-unlockable') as $post_type) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $posts = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type=%s", $post_type)); foreach ($posts as $post_id) \wp_delete_post($post_id, true); } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("TRUNCATE {$wpdb->base_prefix}lws_wr_historic"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("TRUNCATE {$wpdb->prefix}lws_wr_achieved_log"); // do not truncate {$wpdb->base_prefix}lws_wr_tinyurls since such url can be widely shared // user meta - all keys are hardcoded constants $ukeys = array( 'lws_wre_unlocked_id', 'lws_wre_pending_achievement', 'lws_wooreward_used_sponsorship', 'lws_woorewards_sponsored_by', 'lws_woorewards_sponsored_origin', 'lws_woorewards_at_registration_sponsorship', ); $placeholders = \implode(',', \array_fill(0, \count($ukeys), '%s')); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ({$placeholders})", $ukeys)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s", 'lws_wr_redeemed_%')); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE %s", 'lws_wre_points_%')); /// @see \LWS\WOOREWARDS\Core\PointStack::MetaPrefix // post meta // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE 'lws_woorewards_%'"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ('reward_origin','reward_origin_id','wre_pool_point_stack')"); // hpos order meta // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching if ($wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}wc_orders_meta'")) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("DELETE FROM {$wpdb->prefix}wc_orders_meta WHERE meta_key LIKE 'lws_woorewards_%'"); } // mails $prefix = 'lws_mail_' . 'woorewards' . '_attribute_'; \delete_option($prefix . 'headerpic'); \delete_option($prefix . 'footer'); foreach (array('wr_new_reward') as $template) { \delete_option('lws_mail_subject_' . $template); \delete_option('lws_mail_preheader_' . $template); \delete_option('lws_mail_title_' . $template); \delete_option('lws_mail_header_' . $template); \delete_option('lws_mail_template_' . $template); \delete_option('lws_mail_bcc_admin_' . $template); } // clean options // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'lws_woorewards_%'"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'rflush_lws_woorewards_%'"); \do_action('lws_woorewards_after_delete_all', $data); \wp_installing($wpInstalling); return __("You can now create new Points and Rewards System for your customers or uninstall MyRewards.", 'woorewards-lite'); } public function addSponsorshipTab($page) { $current = \LWS\Adminpanel\Tools\Conveniences::getCurrentAdminPage(); if (false === \strpos($current, LWS_WOOREWARDS_PAGE)) return $page; if (isset($page['tabs']['sponsorship'])) return $page; $page['tabs']['sponsorship'] = array( 'id' => 'sponsorship', 'title' => __('Referrals', 'woorewards-lite'), 'icon' => 'lws-icon-b-check', 'vertnav'=> true, 'groups' => array(), ); if ((LWS_WOOREWARDS_PAGE . '.customers') != $current) return $page; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab routing if (!(isset($_REQUEST['tab']) && 'sponsorship' == \sanitize_text_field(\wp_unslash($_REQUEST['tab'])))) return $page; require_once LWS_WOOREWARDS_INCLUDES . '/ui/editlists/sponsorships.php'; $page['tabs']['sponsorship']['groups']['sponsors'] = array( 'id' => 'sponsors_list', 'title' => __("Referrals Information", 'woorewards-lite'), 'icon' => 'lws-icon-b-check', 'color' => '#6e96b5', 'text' => array('tag' => 'ul', __("You will find here a list of all customers who referred other people.", 'woorewards-lite'), sprintf( /* translators: %s: shortcode link */ __("See %s to let your customer share a referral link and get referees.", 'woorewards-lite'), sprintf('%s', \esc_attr(\add_query_arg(array( 'page' => LWS_WOOREWARDS_PAGE . '.appearance', 'tab' => 'shortcodes' ), \admin_url('admin.php#lws_woorewards_referral_link'))), '[wr_referral_link]' ) ), ), 'editlist' => \LWS\WOOREWARDS\Ui\Editlists\Sponsorships::instanciate(), ); return $page; } function restorePointsToDate($btnId, $data = array()) { if ($btnId != 'trigger_restore_points') return false; $poolId = isset($data['restore_points_pool']) ? (int)$data['restore_points_pool'] : 0; if (!$poolId) { return sprintf('%s', __("Please select a loyalty system", 'woorewards-lite')); } $targetDate = isset($data['restore_points_date']) ? \sanitize_text_field(\trim($data['restore_points_date'])) : ''; if (!$targetDate) { return sprintf('%s', __("Please select a date", 'woorewards-lite')); } if (!(isset($data['restore_conf']) && \wp_verify_nonce($data['restore_conf'], 'restorePointsToDate'))) { /* translators: %s: button label */ $label = __("If you really want to restore points, check this box and click on '%s' again.", 'woorewards-lite'); $label = sprintf($label, __("Restore Points", 'woorewards-lite')); $warn = __("This will adjust all users' points in the selected system.", 'woorewards-lite'); $nonce = \esc_attr(\wp_create_nonce('restorePointsToDate')); $str = "" . "" . "" . "
"; return $str; } $targetTime = isset($data['restore_points_time']) ? \sanitize_text_field(\trim($data['restore_points_time'])) : '23:59'; if (!$targetTime) { $targetTime = '23:59'; } $timeParts = explode(':', $targetTime); if (count($timeParts) < 2 || !is_numeric($timeParts[0]) || !is_numeric($timeParts[1])) { return sprintf('%s', __("Invalid time format", 'woorewards-lite')); } $hour = (int)$timeParts[0]; $minute = (int)$timeParts[1]; $second = isset($timeParts[2]) && is_numeric($timeParts[2]) ? (int)$timeParts[2] : 59; if ($hour < 0 || $hour > 23 || $minute < 0 || $minute > 59 || $second < 0 || $second > 59) { return sprintf('%s', __("Invalid time values", 'woorewards-lite')); } $localTimezone = \wp_timezone(); $dateObj = \date_create($targetDate, $localTimezone); if (!$dateObj) { return sprintf('%s', __("Invalid date format", 'woorewards-lite')); } $dateObj->setTime($hour, $minute, $second); $now = new \DateTime('now', $localTimezone); if ($dateObj > $now) { return sprintf('%s', __("Cannot restore to a future date", 'woorewards-lite')); } $targetDateDisplay = $dateObj->format(\get_option('date_format') . ' ' . \get_option('time_format')); $dateObj->setTimezone(new \DateTimeZone('GMT')); $targetDateFormatted = $dateObj->format('Y-m-d H:i:s'); if (\class_exists('\LWS\WOOREWARDS\PRO\Core\Pool')) { $pool = \LWS\WOOREWARDS\PRO\Core\Pool::getOrLoad($poolId, false); } else { $pool = \apply_filters('lws_woorewards_get_pools_by_args', false, array( 'post_id' => $poolId, 'force' => true, )); if ($pool) $pool = $pool->first(); } if (!$pool) { return sprintf('%s', __("The selected loyalty system can't be found", 'woorewards-lite')); } $stackId = $pool->getStackId(); $poolName = $pool->getOption('display_title'); if (!$poolName) { $poolName = $pool->getOption('title', __("Loyalty System", 'woorewards-lite')); } try { global $wpdb; $blogId = \get_current_blog_id(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $historicalBalances = $wpdb->get_results($wpdb->prepare(" SELECT h.user_id, h.new_total as historical_balance FROM {$wpdb->lwsWooRewardsHistoric} h INNER JOIN ( SELECT user_id, MAX(id) as max_id FROM {$wpdb->lwsWooRewardsHistoric} WHERE stack = %s AND mvt_date <= %s AND blog_id = %d GROUP BY user_id ) latest ON h.user_id = latest.user_id AND h.id = latest.max_id ", $stackId, $targetDateFormatted, $blogId), ARRAY_A); $metaKey = \LWS\WOOREWARDS\Core\PointStack::MetaPrefix . $stackId; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $currentHolders = $wpdb->get_results($wpdb->prepare(" SELECT user_id, CAST(meta_value AS SIGNED) as current_points FROM {$wpdb->usermeta} WHERE meta_key = %s AND meta_value != '' ", $metaKey), ARRAY_A); $historicalMap = array(); foreach ($historicalBalances as $row) { $historicalMap[(int)$row['user_id']] = (int)$row['historical_balance']; } \set_time_limit(0); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- long running admin operation /* translators: %s: target date */ $reason = sprintf(__("Points restored to %s", 'woorewards-lite'), $targetDateDisplay); $adjusted = 0; $unchanged = 0; $resetToZero = 0; foreach ($currentHolders as $holder) { $userId = (int)$holder['user_id']; $currentPoints = (int)$holder['current_points']; $targetBalance = isset($historicalMap[$userId]) ? $historicalMap[$userId] : 0; if ($currentPoints === $targetBalance) { $unchanged++; continue; } $stack = new \LWS\WOOREWARDS\Core\PointStack($stackId, $userId); $stack->set($targetBalance, $reason, 'restore_to_date', $poolId); if ($targetBalance === 0) { $resetToZero++; } else { $adjusted++; } } /* translators: %1$s: system name, %2$s: target date */ $message = sprintf(__('Points restoration completed for system %1$s to date %2$s:', 'woorewards-lite'), \esc_html($poolName), $targetDateDisplay); $stats = array(); if ($adjusted > 0) { /* translators: %d: number of users */ $stats[] = sprintf(__("%d user(s) adjusted", 'woorewards-lite'), $adjusted); } if ($resetToZero > 0) { /* translators: %d: number of users */ $stats[] = sprintf(__("%d user(s) reset to zero", 'woorewards-lite'), $resetToZero); } if ($unchanged > 0) { /* translators: %d: number of users */ $stats[] = sprintf(__("%d user(s) unchanged", 'woorewards-lite'), $unchanged); } if (empty($stats)) { $stats[] = __("No users affected", 'woorewards-lite'); } return '%s
', __("An error occurred during point restoration", 'woorewards-lite'), \esc_html($e->getMessage()) ); } } }