- Fetch post titles for pre-selected IDs on mount via include[] param - Cache labels from search results to avoid re-fetching - Filter already-selected items from dropdown results - Add loading spinner and no-results message - Update PHP autocomplete handler to support include[] param - Fix CSS class conflict warning
1128 lines
41 KiB
PHP
1128 lines
41 KiB
PHP
<?php
|
||
namespace Formipay;
|
||
use Formipay\Traits\SingletonTrait;
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||
|
||
class Coupon {
|
||
|
||
use SingletonTrait;
|
||
|
||
/**
|
||
* Initializes the plugin by setting filters and administration functions.
|
||
*/
|
||
|
||
protected function __construct() {
|
||
|
||
add_action( 'init', [$this, 'cpt'] );
|
||
add_action( 'admin_menu', [$this, 'add_submenu'] );
|
||
add_action( 'admin_enqueue_scripts', [$this, 'enqueue_admin'] );
|
||
|
||
add_filter( 'stm_wpcfto_boxes', [$this, 'cpt_post_fields_box'] );
|
||
add_filter( 'stm_wpcfto_fields', [$this, 'cpt_post_fields_content'] );
|
||
add_filter( 'formipay/coupon-config', [$this, 'rule_config'] );
|
||
add_filter( 'formipay/coupon-config', [$this, 'restriction_config'] );
|
||
add_filter( 'formipay/admin-editor/layout/static-elements-sort', [$this, 'add_static_element'] );
|
||
add_action( 'formipay/render/static-element', [$this, 'render_static_element'] );
|
||
|
||
add_action( 'wp_ajax_check_coupon_code', [$this, 'check_coupon_code'] );
|
||
add_action( 'wp_ajax_nopriv_check_coupon_code', [$this, 'check_coupon_code'] );
|
||
|
||
// Admin Page
|
||
add_action( 'wp_ajax_formipay_coupon_get_products', [$this, 'formipay_coupon_get_products'] );
|
||
add_action( 'wp_ajax_formipay-tabledata-coupons', [$this, 'formipay_tabledata_coupons'] );
|
||
add_action( 'wp_ajax_formipay-create-coupon-post', [$this, 'formipay_create_coupon_post'] );
|
||
add_action( 'wp_ajax_formipay-delete-coupon', [$this, 'formipay_delete_coupon'] );
|
||
add_action( 'wp_ajax_formipay-bulk-delete-coupon', [$this, 'formipay_bulk_delete_coupon'] );
|
||
add_action( 'wp_ajax_formipay-duplicate-coupon', [$this, 'formipay_duplicate_coupon'] );
|
||
add_action( 'wp_ajax_formipay-get-coupon', [$this, 'formipay_get_coupon'] );
|
||
add_action( 'wp_ajax_formipay-save-coupon', [$this, 'formipay_save_coupon'] );
|
||
add_action( 'wp_ajax_formipay-autocomplete-search', [$this, 'formipay_autocomplete_search'] );
|
||
|
||
// React Metabox
|
||
add_action( 'add_meta_boxes', [$this, 'add_react_metabox'] );
|
||
add_action( 'admin_footer-post.php', [$this, 'render_react_metabox_template'] );
|
||
|
||
// Order
|
||
add_filter( 'formipay/order/order-details', [$this, 'order_details'], 99, 3 );
|
||
// Paypal
|
||
add_filter( 'formipay/order/paypal/payload/breakdown', [$this, 'add_discount_item'], 99, 3 );
|
||
|
||
}
|
||
|
||
public function cpt() {
|
||
|
||
$labels = array(
|
||
'name' => __('Coupons', 'formipay'),
|
||
'singular_name' => __('Coupon', 'formipay'),
|
||
// 'menu_name' => 'Formipay',
|
||
'add_new' => __('Add New', 'formipay'),
|
||
'add_new_item' => __('Add New Coupon', 'formipay'),
|
||
'edit' => __('Edit', 'formipay'),
|
||
'edit_item' => __('Edit Coupon', 'formipay'),
|
||
'new_item' => __('New Coupon', 'formipay'),
|
||
'view' => __('View', 'formipay'),
|
||
'view_item' => __('View Coupon', 'formipay'),
|
||
'search_items' => __('Search Coupon', 'formipay'),
|
||
'not_found' => __('No coupons found', 'formipay'),
|
||
'not_found_in_trash' => __('No coupons found in trash', 'formipay'),
|
||
'parent' => __('Coupon Parent', 'formipay')
|
||
);
|
||
|
||
$args = array(
|
||
'label' => 'Coupons',
|
||
'description' => __('Coupon for marketing campaign', 'formipay'),
|
||
'labels' => $labels,
|
||
'public' => false,
|
||
'supports' => array( 'title' ),
|
||
'hierarchical' => false,
|
||
'has_archive' => false,
|
||
'show_ui' => true,
|
||
'show_in_menu' => false,
|
||
'show_in_rest' => false,
|
||
'query_var' => true
|
||
);
|
||
|
||
register_post_type( 'formipay-coupon', $args );
|
||
|
||
}
|
||
|
||
public function add_submenu() {
|
||
|
||
add_submenu_page(
|
||
'formipay',
|
||
__( 'Coupons', 'formipay' ),
|
||
__( 'Coupons', 'formipay' ),
|
||
'manage_options',
|
||
'formipay-coupons',
|
||
[$this, 'formipay_coupon'],
|
||
);
|
||
|
||
}
|
||
|
||
public function formipay_coupon() {
|
||
// React admin
|
||
\Formipay\Admin\ReactAdmin::render_mount_point('coupons');
|
||
}
|
||
|
||
public function enqueue_admin() {
|
||
$screen = get_current_screen();
|
||
|
||
// Enqueue SweetAlert2 for coupon post edit screen
|
||
if ($screen && $screen->post_type === 'formipay-coupon' && $screen->base === 'post') {
|
||
wp_enqueue_style('sweetalert2', FORMIPAY_URL . 'vendor/SweetAlert2/sweetalert2.min.css', [], '11.14.4', 'all');
|
||
wp_enqueue_script('sweetalert2', FORMIPAY_URL . 'vendor/SweetAlert2/sweetalert2.min.js', ['jquery'], '11.14.4', true);
|
||
|
||
// Localize admin data
|
||
wp_localize_script('formipay-admin', 'formipayAdmin', [
|
||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||
'siteUrl' => site_url(),
|
||
'nonce' => wp_create_nonce('formipay-admin'),
|
||
]);
|
||
}
|
||
}
|
||
|
||
public function cpt_post_fields_box($boxes) {
|
||
// Disabled - using React metabox instead
|
||
// $boxes['formipay_coupon_settings'] = array(
|
||
// 'post_type' => array('formipay-coupon'),
|
||
// 'label' => __('Details', 'formipay'),
|
||
// );
|
||
|
||
return $boxes;
|
||
}
|
||
|
||
public function cpt_post_fields_content($fields) {
|
||
|
||
$fields['formipay_coupon_settings'] = array();
|
||
|
||
$fields = apply_filters( 'formipay/coupon-config', $fields );
|
||
|
||
return $fields;
|
||
|
||
}
|
||
|
||
public function rule_config($fields) {
|
||
|
||
$multicurrency = formipay_is_multi_currency_active();
|
||
$all_currencies = formipay_currency_as_options();
|
||
$global_selected_currencies = formipay_global_currency_options();
|
||
$global_currencies = formipay_global_currency_options('raw');
|
||
$default_currency = formipay_default_currency();
|
||
|
||
// Group : Rules
|
||
$rules_group_1 = array(
|
||
'rules_general_group' => array(
|
||
'type' => 'group_title',
|
||
'group' => 'started'
|
||
),
|
||
'active' => array(
|
||
'type' => 'checkbox',
|
||
'label' => __( 'Active this coupon', 'formipay' ),
|
||
'value' => true,
|
||
),
|
||
'type' => array(
|
||
'type' => 'radio',
|
||
'label' => __( 'Type', 'formipay' ),
|
||
'required' => true,
|
||
'options' => array(
|
||
'fixed' => __( 'Fixed', 'formipay' ),
|
||
'percentage' => __( 'Percentage', 'formipay' )
|
||
),
|
||
),
|
||
'amount_percentage' => array(
|
||
'type' => 'number',
|
||
'label' => __( 'Amount', 'formipay' ),
|
||
'required' => true,
|
||
'dependency' => array(
|
||
'key' => 'type',
|
||
'value' => 'percentage'
|
||
),
|
||
'group' => 'ended'
|
||
)
|
||
);
|
||
|
||
$rules_group_2 = [];
|
||
|
||
$global_currencies = get_global_currency_array();
|
||
$default_currency = formipay_default_currency();
|
||
|
||
$rules_group_2['discount_amount_wrapper'] = array(
|
||
'type' => 'group_title',
|
||
'label' => __( 'Discount Amount', 'formipay' ),
|
||
'dependency' => array(
|
||
'key' => 'type',
|
||
'value' => 'fixed'
|
||
),
|
||
'group' => 'started',
|
||
);
|
||
|
||
$rules_group_max['discount_max_amount_wrapper'] = array(
|
||
'type' => 'group_title',
|
||
'label' => __( 'Max Discount Amount', 'formipay' ),
|
||
'description' => __( 'Leave empty to not limit the max discount amount.', 'formipay' ),
|
||
'group' => 'started',
|
||
);
|
||
|
||
foreach($global_currencies as $currency){
|
||
$default_currency_symbol = formipay_get_currency_data_by_value($default_currency, 'symbol');
|
||
$currency_symbol = formipay_get_currency_data_by_value($currency['currency'], 'symbol');
|
||
$currency_title = ucwords(formipay_get_currency_data_by_value($currency['currency'], 'title'));
|
||
$decimal_digits = intval($currency['decimal_digits']);
|
||
$step = $decimal_digits * 10;
|
||
$step = $step > 0 ? 1 / $step : 1;
|
||
|
||
$rules_group_2['amount_fixed_'.$currency_symbol] = array(
|
||
'type' => 'number',
|
||
'label' => sprintf(
|
||
__( '<img src="%s" width="18" /> Amount in %s', 'formipay' ),
|
||
formipay_get_flag_by_currency($currency['currency']),
|
||
$currency_symbol
|
||
),
|
||
'step' => $step,
|
||
'min' => 0,
|
||
'required' => true,
|
||
'placeholder' => __( 'Enter Amount...', 'formipay' ),
|
||
'dependency' => array(
|
||
'key' => 'type',
|
||
'value' => 'fixed'
|
||
)
|
||
);
|
||
|
||
$rules_group_max['max_amount_'.$currency_symbol] = array(
|
||
'type' => 'number',
|
||
'label' => sprintf(
|
||
__( '<img src="%s" width="18" /> Max Amount in %s', 'formipay' ),
|
||
formipay_get_flag_by_currency($currency['currency']),
|
||
$currency_symbol
|
||
),
|
||
'step' => $step,
|
||
'min' => 0,
|
||
'placeholder' => __( 'Enter Max Amount...', 'formipay' )
|
||
);
|
||
|
||
}
|
||
$last_rules_group_2 = array_key_last($rules_group_2);
|
||
$rules_group_2[$last_rules_group_2]['group'] = 'ended';
|
||
|
||
$last_rules_group_max = array_key_last($rules_group_max);
|
||
$rules_group_max[$last_rules_group_max]['group'] = 'ended';
|
||
|
||
$rules_group_3 = array(
|
||
'rules_group' => array(
|
||
'type' => 'group_title',
|
||
'label' => __( 'Rules', 'formipay' ),
|
||
'description' => __( 'Define the rules of this coupon.', 'formipay' ),
|
||
'group' => 'started'
|
||
),
|
||
'case_sensitive' => array(
|
||
'type' => 'checkbox',
|
||
'label' => __( 'Case Sensitive', 'formipay' ),
|
||
'description' => __( 'If this activated, coupon codes must be entered with the exact capitalization as specified. <br>
|
||
For example code <B>SAVE10</b>:<br>
|
||
- <b>SAVE10</b> is valid<br>
|
||
- <b>save10</b> is invalid<br>
|
||
- <b>Save10</b> is invalid.', 'formipay' )
|
||
),
|
||
'free_shipping' => array(
|
||
'type' => 'checkbox',
|
||
'label' => __( 'Free Shipping', 'formipay' ),
|
||
'description' => __( 'Shipping cost will be free when this coupon applied.', 'formipay' )
|
||
),
|
||
'quantity_active' => array(
|
||
'type' => 'checkbox',
|
||
'label' => __( 'Influenced by Quantity', 'formipay' ),
|
||
'description' => __( 'Example: when buyer buy 4 pcs of item, 4 × discount amount will be implemented.', 'formipay' ),
|
||
'dependency' => array(
|
||
'key' => 'type',
|
||
'value' => 'fixed'
|
||
)
|
||
),
|
||
// 'max_discount' => array(
|
||
// 'type' => 'number',
|
||
// 'label' => __( 'Max Discount Amount', 'formipay' ),
|
||
// 'description' => __( 'Leave it empty to not limit the max discount amount.', 'formipay' )
|
||
// ),
|
||
);
|
||
|
||
$rules_group = $rules_group_1 + $rules_group_2 + $rules_group_max + $rules_group_3;
|
||
|
||
$rules_group = apply_filters( 'formipay/coupon-settings/tab:rules/group:rules', $rules_group );
|
||
|
||
$last_rules_group = array_key_last($rules_group);
|
||
$rules_group[$last_rules_group]['group'] = 'ended';
|
||
|
||
$all_group_merged = $rules_group;
|
||
|
||
$settings_all_fields = apply_filters( 'formipay/coupon-settings/tab:rules', $all_group_merged );
|
||
|
||
$settings_fields = [];
|
||
if(!empty($settings_all_fields)){
|
||
foreach($settings_all_fields as $key => $value){
|
||
$settings_fields[$key] = $value;
|
||
}
|
||
}
|
||
|
||
$fields['formipay_coupon_settings']['rules'] = array(
|
||
'name' => __('Rules', 'formipay'),
|
||
'fields' => $settings_fields
|
||
);
|
||
|
||
return $fields;
|
||
|
||
}
|
||
|
||
public function restriction_config($fields) {
|
||
|
||
// Group : Restrictions
|
||
$restriction_group = array(
|
||
'restriction_group' => array(
|
||
'type' => 'group_title',
|
||
'label' => __( 'Restrictions', 'formipay' ),
|
||
'group' => 'started'
|
||
),
|
||
'use_limit' => array(
|
||
'type' => 'number',
|
||
'label' => __( 'Usage Limit', 'formipay' ),
|
||
'description' => __( 'Leave it empty or 0 (zero) to set it as unlimited usage.', 'formipay' )
|
||
),
|
||
'date_limit' => array(
|
||
'type' => 'date',
|
||
'label' => __( 'Date Limit', 'formipay' ),
|
||
'description' => __( 'Chosen date is the last day the coupon can be used. Leave it empty tio set it as no-limit date.', 'formipay' )
|
||
),
|
||
'forms' => array(
|
||
'type' => 'autocomplete',
|
||
'post_type' => array('formipay-form'),
|
||
'label' => __( 'Forms', 'formipay' ),
|
||
'description' => __( 'Only selected form(s) can use the coupon. Leave empty to apply to all forms.', 'formipay' )
|
||
),
|
||
'products' => array(
|
||
'type' => 'autocomplete',
|
||
'post_type' => array('formipay-product'),
|
||
'label' => __( 'Products', 'formipay' ),
|
||
'description' => __( 'Only selected product(s) can use the coupon. Leave empty to apply to all products.', 'formipay' )
|
||
),
|
||
'customers' => array(
|
||
'type' => 'autocomplete',
|
||
'post_type' => array('formipay-product'),
|
||
'label' => __( 'Customers', 'formipay' ),
|
||
'description' => __( 'Only selected customer(s) can use the coupon. Leave empty to apply to all customers.', 'formipay' )
|
||
)
|
||
);
|
||
|
||
$restriction_group = apply_filters( 'formipay/coupon-settings/tab:restriction/group:restrictions', $restriction_group );
|
||
|
||
$last_restriction_group = array_key_last($restriction_group);
|
||
$restriction_group[$last_restriction_group]['group'] = 'ended';
|
||
|
||
$details_all_fields = apply_filters( 'formipay/coupon-settings/tab:restriction', $restriction_group );
|
||
|
||
$details_fields = [];
|
||
if(!empty($details_all_fields)){
|
||
foreach($details_all_fields as $key => $value){
|
||
$details_fields[$key] = $value;
|
||
}
|
||
}
|
||
|
||
$fields['formipay_coupon_settings']['restriction'] = array(
|
||
'name' => __('Restrictions', 'formipay'),
|
||
'fields' => $details_fields
|
||
);
|
||
|
||
return $fields;
|
||
|
||
}
|
||
|
||
public function add_static_element($elements) {
|
||
|
||
$elements[] = [
|
||
'id' => 'coupon_field',
|
||
'label' => __( 'Coupon Field', 'formipay' )
|
||
];
|
||
|
||
return $elements;
|
||
|
||
}
|
||
|
||
public function render_static_element($element_id) {
|
||
|
||
if($element_id == 'coupon_field'){
|
||
?>
|
||
<div class="formipay-field-group">
|
||
<div class="formipay-coupon-field-group">
|
||
<input type="text" name="coupon_code"
|
||
class="formipay-input formipay-code-input"
|
||
value="<?php echo
|
||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||
isset($_GET['coupon']) ? esc_attr( sanitize_text_field( wp_unslash($_GET['coupon']) ) ) : ''
|
||
?>" placeholder="<?php echo esc_attr__('Your coupon code', 'formipay'); ?>"
|
||
data-label="<?php echo esc_attr__('Coupon Code', 'formipay'); ?>">
|
||
<button type="button" data-text="<?php echo esc_attr__( 'Apply', 'formipay' ); ?>" data-checking="<?php echo esc_attr__( 'Checking...', 'formipay' ); ?>" id="apply_coupon_code"><?php echo esc_attr__( 'Apply', 'formipay' ); ?></button>
|
||
</div>
|
||
<div class="formipay-coupon-alert-message"></div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
}
|
||
|
||
public function check_coupon_code() {
|
||
|
||
check_ajax_referer( 'formipay-frontend-nonce', 'security' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$code = isset($_REQUEST['code']) ? sanitize_text_field( wp_unslash($_REQUEST['code']) ) : '';
|
||
$form_id = isset($_REQUEST['form']) ? intval( $_REQUEST['form'] ) : 0;
|
||
|
||
$check_code = formipay_get_coupon_id_by_code($code, $form_id);
|
||
|
||
if(false == $check_code){
|
||
wp_send_json_error( [
|
||
'message' => __( 'Coupon code is not valid', 'formipay' )
|
||
] );
|
||
}
|
||
|
||
wp_send_json_success();
|
||
|
||
}
|
||
|
||
public function order_details($details, $form_id, $order_data) {
|
||
|
||
if( isset($order_data['coupon_code']) && !empty($order_data['coupon_code']) ) {
|
||
|
||
$coupon_id = formipay_get_coupon_id_by_code( sanitize_text_field( $order_data['coupon_code'] ), $form_id );
|
||
|
||
if(false !== $coupon_id) {
|
||
|
||
$amount = floatval( formipay_get_post_meta( $coupon_id, 'amount' ) );
|
||
$discount = $amount;
|
||
$coupon_type = formipay_get_post_meta( $coupon_id, 'type' );
|
||
|
||
$qty = 1;
|
||
if( formipay_get_post_meta( $form_id, 'product_quantity_toggle' ) == 'on' ){
|
||
$qty = intval($order_data['qty']);
|
||
}
|
||
|
||
if( $coupon_type == 'percentage' ){
|
||
$product_price = floatval( formipay_get_post_meta( $form_id, 'product_price' ) );
|
||
$amount = $amount / 100;
|
||
$discount = $product_price * $amount;
|
||
}
|
||
|
||
$amount = $discount * $qty;
|
||
$amount = $amount * -1;
|
||
|
||
$details[] = [
|
||
'item' => esc_html( $order_data['coupon_code'] ),
|
||
'amount' => floatval($amount),
|
||
'subtotal' => floatval($amount),
|
||
'context' => 'sub'
|
||
];
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return $details;
|
||
|
||
}
|
||
|
||
public function count_order_by_coupon_code($coupon_code) {
|
||
|
||
global $wpdb;
|
||
$table = $wpdb->prefix .'formipay_orders';
|
||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
||
$data = $wpdb->get_results(
|
||
$wpdb->prepare(
|
||
"SELECT COUNT(id) as count FROM %i WHERE `items` LIKE %s", $table, '%' . $wpdb->esc_like($coupon_code) . '%'
|
||
)
|
||
);
|
||
|
||
return $data[0]->count;
|
||
|
||
}
|
||
|
||
public function add_discount_item($breakdown, $currency, $order_data) {
|
||
|
||
if( isset($order_data['form_data']['coupon_code']) && !empty($order_data['form_data']['coupon_code']) ) {
|
||
|
||
$form_id = $order_data['form_id'];
|
||
$coupon_id = formipay_get_coupon_id_by_code( sanitize_text_field( $order_data['form_data']['coupon_code'] ), $form_id );
|
||
|
||
if(false !== $coupon_id) {
|
||
|
||
$amount = floatval( formipay_get_post_meta( $coupon_id, 'amount' ) );
|
||
$discount = $amount;
|
||
$coupon_type = formipay_get_post_meta( $coupon_id, 'type' );
|
||
|
||
$qty = 1;
|
||
if( formipay_get_post_meta( $form_id, 'product_quantity_toggle' ) == 'on' ){
|
||
$qty = intval($order_data['form_data']['qty']);
|
||
}
|
||
|
||
if( $coupon_type == 'percentage' ){
|
||
$product_price = floatval( formipay_get_post_meta( $form_id, 'product_price' ) );
|
||
$amount = $amount / 100;
|
||
$discount = $product_price * $amount;
|
||
}
|
||
|
||
$breakdown['item_total']['value'] += $discount;
|
||
$breakdown['discount'] = array(
|
||
"currency_code" => $currency,
|
||
"value" => $discount
|
||
);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return $breakdown;
|
||
|
||
}
|
||
|
||
public function formipay_tabledata_coupons() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$args = [
|
||
'post_type' => 'formipay-coupon',
|
||
'posts_per_page' => -1,
|
||
'post_status' => array( 'pending', 'draft', 'publish' )
|
||
];
|
||
|
||
$get_total_coupons = get_posts($args);
|
||
|
||
$coupon_status = [
|
||
'all' => 0,
|
||
'active' => 0,
|
||
'inactive' => 0
|
||
];
|
||
if(!empty($get_total_coupons)){
|
||
foreach($get_total_coupons as $coupon){
|
||
$status = (formipay_get_post_meta($coupon->ID, 'active') == 'on') ? 'active' : 'inactive';
|
||
$coupon_status['all'] = intval($coupon_status['all']) + 1;
|
||
if($status == 'active'){
|
||
$coupon_status['active'] = intval($coupon_status['active']) + 1;
|
||
}elseif($status == 'inactive'){
|
||
$coupon_status['inactive'] = intval($coupon_status['inactive']) + 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(isset($_REQUEST['limit'])){
|
||
$args['posts_per_page'] = intval($_REQUEST['limit']);
|
||
}
|
||
|
||
if(isset($_REQUEST['offset'])){
|
||
$args['offset'] = intval($_REQUEST['offset']);
|
||
}
|
||
|
||
if(!empty($_REQUEST['search'])){
|
||
$args['s'] = sanitize_text_field( wp_unslash($_REQUEST['search']) );
|
||
}
|
||
|
||
// Handle status filtering (active/inactive)
|
||
$status_filter = isset($_REQUEST['status']) ? sanitize_text_field($_REQUEST['status']) : 'all';
|
||
|
||
$get_coupons = get_posts($args);
|
||
$global_currencies = get_global_currency_array();
|
||
|
||
$coupons = [];
|
||
if(!empty($get_coupons)){
|
||
foreach($get_coupons as $key => $coupon){
|
||
|
||
$is_active = formipay_get_post_meta($coupon->ID, 'active') == 'on';
|
||
|
||
// Apply status filter
|
||
if ($status_filter !== 'all') {
|
||
if ($status_filter === 'active' && !$is_active) continue;
|
||
if ($status_filter === 'inactive' && $is_active) continue;
|
||
}
|
||
|
||
$date_limit = formipay_get_post_meta($coupon->ID, 'date_limit');
|
||
|
||
$type = formipay_get_post_meta($coupon->ID, 'type');
|
||
$amount_meta_key = "amount_$type";
|
||
|
||
if($type == 'fixed'){
|
||
$amount_value = [];
|
||
foreach($global_currencies as $currency){
|
||
$raw = $currency['currency'];
|
||
$decimal_digits = $currency['decimal_digits'];
|
||
$decimal_symbol = $currency['decimal_symbol'];
|
||
$thousand_separator = $currency['thousand_separator'];
|
||
$parse_currency = explode(':::', $raw);
|
||
$currency_code = $parse_currency[0];
|
||
$amount_in_currency = formipay_get_post_meta($coupon->ID, 'amount_fixed_'.$currency_code);
|
||
$amount_value[] = [
|
||
'raw' => $raw,
|
||
'amount' => number_format($amount_in_currency, $decimal_digits, $decimal_symbol, $thousand_separator),
|
||
'flag' => formipay_get_flag_by_currency($raw)
|
||
];
|
||
}
|
||
}else{
|
||
$amount_value = floatval(formipay_get_post_meta($coupon->ID, $amount_meta_key));
|
||
}
|
||
|
||
|
||
|
||
$coupons[] = [
|
||
'ID' => $coupon->ID,
|
||
'code' => get_the_title($coupon->ID),
|
||
'amount' => $amount_value,
|
||
'type' => ucfirst(formipay_get_post_meta($coupon->ID, 'type')),
|
||
'case_sensitive' => formipay_get_post_meta($coupon->ID, 'case_sensitive'),
|
||
'usage_count' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)),
|
||
'usages' => $this->count_order_by_coupon_code(get_the_title($coupon->ID)),
|
||
'date_limit' => false !== $date_limit ? formipay_date('Y-m-d', intval(formipay_get_post_meta($coupon->ID, 'date_limit')) / 1000) : 'none',
|
||
'active' => $is_active ? 'on' : 'off',
|
||
'post_status' => $is_active ? 'active' : 'inactive',
|
||
'status' => $is_active ? 'active' : 'inactive'
|
||
];
|
||
}
|
||
}
|
||
|
||
$response = [
|
||
'results' => $coupons,
|
||
'total' => count($get_total_coupons), // Total number of forms
|
||
'posts_report' => array_map('intval', (array)$coupon_status)
|
||
];
|
||
|
||
wp_send_json($response);
|
||
}
|
||
|
||
public function formipay_coupon_get_products() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
if (!isset($_POST['search']) || empty($_POST['search'])) {
|
||
wp_send_json_error( __('No search term provided.', 'formipay') );
|
||
}
|
||
|
||
$search_term = sanitize_text_field( wp_unslash($_POST['search']) );
|
||
|
||
$query = get_posts([
|
||
'post_type' => 'formipay-form',
|
||
's' => $search_term,
|
||
'posts_per_page' => -1,
|
||
]);
|
||
|
||
$results = [];
|
||
if(!empty($query)){
|
||
foreach($query as $post){
|
||
$results[] = [
|
||
'value' => $post->ID,
|
||
'label' => $post->post_title,
|
||
];
|
||
}
|
||
}
|
||
|
||
wp_send_json($results);
|
||
|
||
}
|
||
|
||
public function formipay_create_coupon_post() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$code = isset($_REQUEST['title']) ? sanitize_text_field( wp_unslash($_REQUEST['title']) ) : '';
|
||
|
||
if( !empty($code) && '' !== $code ){
|
||
$post_id = wp_insert_post( [
|
||
'post_title' => $code,
|
||
'post_type' => 'formipay-coupon',
|
||
], true );
|
||
|
||
if(is_wp_error($post_id)){
|
||
wp_send_json_error( [
|
||
'message' => $post_id->get_error_message()
|
||
] );
|
||
}
|
||
|
||
update_post_meta($post_id, 'type', 'percentage');
|
||
update_post_meta($post_id, 'amount', 0);
|
||
wp_send_json_success( [
|
||
'edit_post_url' => admin_url('post.php?post='.$post_id.'&action=edit')
|
||
] );
|
||
}
|
||
|
||
wp_send_json_error( [
|
||
'message' => esc_html__( 'Coupon code is empty.', 'formipay' )
|
||
] );
|
||
|
||
}
|
||
|
||
public function formipay_delete_coupon() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||
|
||
$delete = wp_delete_post($post_id, true);
|
||
|
||
if(is_wp_error( $delete )){
|
||
wp_send_json_error( [
|
||
'title' => esc_html__( 'Failed', 'formipay' ),
|
||
'message' => esc_html__( 'Failed to delete coupon. Please try again.', 'formipay' ),
|
||
'icon' => 'error'
|
||
] );
|
||
}
|
||
|
||
wp_send_json_success( [
|
||
'title' => esc_html__( 'Deleted', 'formipay' ),
|
||
'message' => esc_html__( 'Coupon is deleted permanently.', 'formipay' ),
|
||
'icon' => 'success'
|
||
] );
|
||
|
||
}
|
||
|
||
public function formipay_bulk_delete_coupon() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
if( empty($_REQUEST['ids']) ){
|
||
wp_send_json_error( [
|
||
'title' => esc_html__( 'Failed', 'formipay' ),
|
||
'message' => esc_html__( 'There is no coupon selected. Please try again.', 'formipay' ),
|
||
'icon' => 'error'
|
||
] );
|
||
}
|
||
|
||
$ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : [];
|
||
|
||
$success = 0;
|
||
$failed = 0;
|
||
$report = __( 'Done.', 'formipay' );
|
||
if(!empty($ids)){
|
||
foreach($ids as $id){
|
||
$delete = wp_delete_post($id, true);
|
||
if(is_wp_error( $delete )){
|
||
$failed++;
|
||
}else{
|
||
$success++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if($success > 0){
|
||
$report .= sprintf( __( ' Deleted %d coupon(s).', 'formipay' ), $success);
|
||
}
|
||
if($failed > 0){
|
||
$report .= sprintf( __( ' Failed %d coupon(s).', 'formipay' ), $failed);
|
||
}
|
||
|
||
wp_send_json_success( [
|
||
'title' => esc_html__( 'Done!', 'formipay' ),
|
||
'message' => $report,
|
||
'icon' => 'info'
|
||
] );
|
||
|
||
}
|
||
|
||
public function formipay_duplicate_coupon() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||
$post = get_post($post_id);
|
||
if (!$post) {
|
||
wp_send_json_error( [
|
||
'title' => esc_html__('Failed', 'formipay'),
|
||
'message' => esc_html__( 'Coupon is not defined.', 'formipay' ),
|
||
'icon' => 'error'
|
||
] );
|
||
}
|
||
|
||
if (!in_array($post->post_type, ['formipay-coupon'])) {
|
||
wp_send_json_error( [
|
||
'title' => esc_html__('Failed', 'formipay'),
|
||
'message' => esc_html__( 'Wrong Post Type.', 'formipay' ),
|
||
'icon' => 'error'
|
||
] );
|
||
}
|
||
|
||
$duplicate_post = [
|
||
'post_title' => $post->post_title . ' ' . __('Copy', 'formipay'),
|
||
'post_content' => $post->post_content,
|
||
'post_status' => 'draft', // Set sebagai draft
|
||
'post_type' => $post->post_type,
|
||
'post_author' => $post->post_author,
|
||
];
|
||
|
||
// Masukkan duplikat ke database
|
||
$new_post_id = wp_insert_post($duplicate_post);
|
||
|
||
if (is_wp_error($new_post_id)) {
|
||
wp_send_json_error( [
|
||
'title' => esc_html__('Failed', 'formipay'),
|
||
'message' => esc_html__( 'Something happened. Please try again.', 'formipay' ),
|
||
'icon' => 'error'
|
||
] );
|
||
}
|
||
|
||
// Salin semua meta data
|
||
$meta_data = get_post_meta($post_id);
|
||
foreach ($meta_data as $key => $values) {
|
||
if($key !== 'forms'){
|
||
foreach ($values as $value) {
|
||
add_post_meta($new_post_id, $key, maybe_unserialize($value));
|
||
}
|
||
}
|
||
}
|
||
|
||
wp_send_json_success( [
|
||
'title' => esc_html__('Duplicated!', 'formipay'),
|
||
'message' => esc_html__( 'Coupon is successfully duplicated.', 'formipay' ),
|
||
'icon' => 'success'
|
||
] );
|
||
}
|
||
|
||
/**
|
||
* Get coupon data for React editor
|
||
*/
|
||
public function formipay_get_coupon() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||
|
||
if ( empty($post_id) ) {
|
||
wp_send_json_error( [ 'message' => esc_html__( 'Coupon ID is required.', 'formipay' ) ] );
|
||
}
|
||
|
||
$post = get_post($post_id);
|
||
if ( ! $post || $post->post_type !== 'formipay-coupon' ) {
|
||
wp_send_json_error( [ 'message' => esc_html__( 'Coupon not found.', 'formipay' ) ] );
|
||
}
|
||
|
||
$global_currencies = get_global_currency_array();
|
||
|
||
// Build coupon data
|
||
$coupon_data = [
|
||
'ID' => $post_id,
|
||
'post_title' => $post->post_title,
|
||
'active' => formipay_get_post_meta($post_id, 'active'),
|
||
'type' => formipay_get_post_meta($post_id, 'type'),
|
||
'amount_percentage' => formipay_get_post_meta($post_id, 'amount_percentage'),
|
||
'case_sensitive' => formipay_get_post_meta($post_id, 'case_sensitive'),
|
||
'free_shipping' => formipay_get_post_meta($post_id, 'free_shipping'),
|
||
'quantity_active' => formipay_get_post_meta($post_id, 'quantity_active'),
|
||
'use_limit' => formipay_get_post_meta($post_id, 'use_limit'),
|
||
'date_limit' => formipay_get_post_meta($post_id, 'date_limit'),
|
||
'amounts_fixed' => [],
|
||
'max_amounts' => [],
|
||
'forms' => formipay_get_post_meta($post_id, 'forms') ?: [],
|
||
'products' => formipay_get_post_meta($post_id, 'products') ?: [],
|
||
'customers' => formipay_get_post_meta($post_id, 'customers') ?: [],
|
||
];
|
||
|
||
// Get fixed amounts for each currency
|
||
foreach ($global_currencies as $currency) {
|
||
$currency_raw = $currency['currency'];
|
||
$currency_parts = explode(':::', $currency_raw);
|
||
$currency_code = $currency_parts[0] ?? '';
|
||
$symbol = formipay_get_currency_data_by_value($currency_raw, 'symbol');
|
||
|
||
$amount_fixed = formipay_get_post_meta($post_id, 'amount_fixed_' . $symbol);
|
||
if ( $amount_fixed ) {
|
||
$coupon_data['amounts_fixed'][] = [
|
||
'currency' => $currency_code,
|
||
'symbol' => $symbol,
|
||
'amount' => $amount_fixed,
|
||
];
|
||
}
|
||
|
||
$max_amount = formipay_get_post_meta($post_id, 'max_amount_' . $symbol);
|
||
if ( $max_amount ) {
|
||
$coupon_data['max_amounts'][] = [
|
||
'currency' => $currency_code,
|
||
'symbol' => $symbol,
|
||
'amount' => $max_amount,
|
||
];
|
||
}
|
||
}
|
||
|
||
wp_send_json_success( $coupon_data );
|
||
}
|
||
|
||
/**
|
||
* Save coupon data from React editor
|
||
*/
|
||
public function formipay_save_coupon() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$post_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;
|
||
$title = isset($_REQUEST['title']) ? sanitize_text_field(wp_unslash($_REQUEST['title'])) : '';
|
||
|
||
if ( empty($title) ) {
|
||
wp_send_json_error( [ 'message' => esc_html__( 'Coupon code is required.', 'formipay' ) ] );
|
||
}
|
||
|
||
$global_currencies = get_global_currency_array();
|
||
|
||
// Prepare post data
|
||
$post_data = [
|
||
'post_title' => $title,
|
||
'post_type' => 'formipay-coupon',
|
||
'post_status' => 'publish',
|
||
];
|
||
|
||
if ( $post_id > 0 ) {
|
||
$post_data['ID'] = $post_id;
|
||
$post_data['post_status'] = get_post_status($post_id);
|
||
$new_post_id = wp_update_post($post_data);
|
||
} else {
|
||
$new_post_id = wp_insert_post($post_data);
|
||
}
|
||
|
||
if ( is_wp_error($new_post_id) ) {
|
||
wp_send_json_error( [ 'message' => $new_post_id->get_error_message() ] );
|
||
}
|
||
|
||
// Save meta fields
|
||
$meta_fields = [
|
||
'active',
|
||
'type',
|
||
'amount_percentage',
|
||
'case_sensitive',
|
||
'free_shipping',
|
||
'quantity_active',
|
||
'use_limit',
|
||
'date_limit',
|
||
];
|
||
|
||
foreach ($meta_fields as $field) {
|
||
$value = isset($_REQUEST[$field]) ? wp_unslash($_REQUEST[$field]) : '';
|
||
update_post_meta($new_post_id, $field, $value);
|
||
}
|
||
|
||
// Save fixed amounts
|
||
foreach ($global_currencies as $currency) {
|
||
$symbol = formipay_get_currency_data_by_value($currency['currency'], 'symbol');
|
||
|
||
if ( isset($_REQUEST['amount_fixed_' . $symbol]) ) {
|
||
update_post_meta($new_post_id, 'amount_fixed_' . $symbol, wp_unslash($_REQUEST['amount_fixed_' . $symbol]));
|
||
}
|
||
|
||
if ( isset($_REQUEST['max_amount_' . $symbol]) ) {
|
||
update_post_meta($new_post_id, 'max_amount_' . $symbol, wp_unslash($_REQUEST['max_amount_' . $symbol]));
|
||
}
|
||
}
|
||
|
||
// Save relation fields
|
||
$relation_fields = ['forms', 'products', 'customers'];
|
||
foreach ($relation_fields as $field) {
|
||
if ( isset($_REQUEST[$field]) ) {
|
||
$values = is_array($_REQUEST[$field]) ? array_map('intval', $_REQUEST[$field]) : [];
|
||
update_post_meta($new_post_id, $field, $values);
|
||
}
|
||
}
|
||
|
||
wp_send_json_success( [
|
||
'message' => esc_html__( 'Coupon saved successfully.', 'formipay' ),
|
||
'id' => $new_post_id,
|
||
] );
|
||
}
|
||
|
||
/**
|
||
* Add React metabox for coupon editor
|
||
*/
|
||
public function add_react_metabox() {
|
||
add_meta_box(
|
||
'formipay_coupon_reactor_metabox',
|
||
__( 'Coupon Settings', 'formipay' ),
|
||
[$this, 'render_react_metabox'],
|
||
'formipay-coupon',
|
||
'normal',
|
||
'high'
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Render React metabox container
|
||
*/
|
||
public function render_react_metabox($post) {
|
||
?>
|
||
<div
|
||
data-formipay-metabox="coupon"
|
||
data-post-id="<?php echo esc_attr($post->ID); ?>"
|
||
class="formipay-react-metabox-container"
|
||
>
|
||
<div class="formipay-loading">
|
||
<div class="formipay-spinner"></div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render React metabox template (hidden)
|
||
*/
|
||
public function render_react_metabox_template() {
|
||
global $post;
|
||
|
||
if (!$post || $post->post_type !== 'formipay-coupon') {
|
||
return;
|
||
}
|
||
|
||
// Get global currencies
|
||
$global_currencies = get_global_currency_array();
|
||
|
||
?>
|
||
<script type="text/javascript">
|
||
window.formipayGlobalCurrencies = <?php echo wp_json_encode($global_currencies); ?>;
|
||
window.formipayGetFlag = function(currencyRaw) {
|
||
<?php
|
||
foreach ($global_currencies as $currency) {
|
||
echo 'if (currencyRaw === "' . esc_js($currency['currency']) . '") return "' . esc_url(formipay_get_flag_by_currency($currency['currency'])) . '";';
|
||
}
|
||
?>
|
||
return '';
|
||
};
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Autocomplete search for relation fields
|
||
*/
|
||
public function formipay_autocomplete_search() {
|
||
|
||
check_ajax_referer( 'formipay-admin', '_wpnonce' );
|
||
|
||
if ( ! current_user_can( 'manage_options' ) ) {
|
||
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
|
||
}
|
||
|
||
$post_type = isset($_REQUEST['post_type']) ? sanitize_text_field(wp_unslash($_REQUEST['post_type'])) : '';
|
||
$search = isset($_REQUEST['search']) ? sanitize_text_field(wp_unslash($_REQUEST['search'])) : '';
|
||
$include = isset($_REQUEST['include']) ? array_map('intval', (array) $_REQUEST['include']) : [];
|
||
|
||
if (empty($post_type)) {
|
||
wp_send_json_error( [ 'message' => 'Invalid request' ] );
|
||
}
|
||
|
||
// Resolve labels for specific IDs (pre-selected items)
|
||
if (!empty($include)) {
|
||
$query = get_posts([
|
||
'post_type' => $post_type,
|
||
'post__in' => $include,
|
||
'posts_per_page' => -1,
|
||
'post_status' => 'any',
|
||
]);
|
||
$results = [];
|
||
if (!empty($query)) {
|
||
foreach ($query as $post) {
|
||
$results[] = [
|
||
'value' => $post->ID,
|
||
'label' => $post->post_title,
|
||
];
|
||
}
|
||
}
|
||
wp_send_json_success($results);
|
||
return;
|
||
}
|
||
|
||
// Search by keyword
|
||
if (strlen($search) < 2) {
|
||
wp_send_json_error( [ 'message' => 'Invalid request' ] );
|
||
}
|
||
|
||
$query = get_posts([
|
||
'post_type' => $post_type,
|
||
's' => $search,
|
||
'posts_per_page' => 20,
|
||
'post_status' => ['publish', 'draft'],
|
||
]);
|
||
|
||
$results = [];
|
||
if (!empty($query)) {
|
||
foreach ($query as $post) {
|
||
$results[] = [
|
||
'value' => $post->ID,
|
||
'label' => $post->post_title,
|
||
];
|
||
}
|
||
}
|
||
|
||
wp_send_json_success($results);
|
||
}
|
||
|
||
}
|