Plugin Directory

Changeset 3173906


Ignore:
Timestamp:
10/22/2024 08:31:40 PM (17 months ago)
Author:
rashedulhaquerumi
Message:

Update-v1.9

Location:
bd-courier-order-ratio-checker/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • bd-courier-order-ratio-checker/trunk/bd-courier-order-ratio-checker.php

    r3163388 r3173906  
    44 * Plugin URI: https://rasedulhaque.com/bd-courier-order-ratio-checker
    55 * Description: A plugin to show customer order ratio from BD Courier with settings and search functionality.
    6  * Version: 1.8
     6 * Version: 1.9
    77 * Author: Rasedul Haque
    8  * Author URI: https://rashedulhaque.com
     8 * Author URI: https://rasedulhaque.com
    99 * Text Domain: bd-courier-order-ratio-checker
    1010 * License: GPLv2 or later
     
    1616}
    1717
    18 class Order_Ratio_Checker {
    19 
    20     /**
    21      * Constructor to initialize hooks and actions.
    22      */
    23     public function __construct() {
    24         // Hook for loading frontend-side scripts (for search form)
    25         add_action('wp_enqueue_scripts', [$this, 'enqueue_search_script']);
    26         add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
    27 
    28         // Add menu for search page in WordPress Admin
    29         add_action('admin_menu', [$this, 'add_bd_courier_menu']);
    30 
    31         // Hook for settings page and submenu
    32         add_action('admin_menu', [$this, 'add_bd_courier_settings_page']);
    33         add_action('admin_init', [$this, 'register_bd_courier_settings']);
    34 
    35         // Shortcode for search form
    36         add_shortcode('bdcourier_search', [$this, 'display_search_form']);
    37 
    38         // Ajax action for search form (both for logged-in and guest users)
    39         add_action('wp_ajax_search_courier_data', [$this, 'search_courier_data']);
    40         add_action('wp_ajax_nopriv_search_courier_data', [$this, 'search_courier_data']);
    41 
    42         // Hook to display data on WooCommerce admin order edit page
    43         add_action('woocommerce_admin_order_data_after_order_details', [$this, 'display_order_ratio_in_admin']);
    44        
    45         // Hook for the AJAX request (for logged-in users)
    46         add_action('wp_ajax_refresh_courier_data', [$this, 'refresh_courier_data']);
    47     }
    48 
    49     /**
    50      * Enqueue admin-side scripts for handling order details page Ajax requests.
    51      */
    52     public function enqueue_admin_scripts( $hook_suffix ) {
    53         // For the BD Courier search page
    54         if ( 'toplevel_page_bd-courier-search' === $hook_suffix ) {
    55             wp_enqueue_script( 'jquery' );
    56             wp_enqueue_script(
    57                 'bdcourier-search-ajax',
    58                 plugin_dir_url( __FILE__ ) . 'bdcourier-search-ajax.js',
    59                 [ 'jquery' ],
    60                 null,
    61                 true
    62             );
    63             wp_localize_script(
    64                 'bdcourier-search-ajax',
    65                 'bdcourierSearchAjax',
    66                 [
    67                     'ajaxurl' => admin_url( 'admin-ajax.php' ),
    68                     'nonce'   => wp_create_nonce( 'bdcourier_search_nonce' ), // Nonce creation
    69                 ]
    70             );
    71         }
    72 
    73    
    74             wp_enqueue_script( 'jquery' );
    75             wp_enqueue_script(
    76                 'order-ratio-ajax',
    77                 plugin_dir_url( __FILE__ ) . 'order-ratio-ajax.js',
    78                 [ 'jquery' ],
    79                 null,
    80                 true
    81             );
    82             wp_localize_script(
    83                 'order-ratio-ajax',
    84                 'orderRatioAjax',
    85                 [
    86                     'ajaxurl' => admin_url( 'admin-ajax.php' ),
    87                     'nonce'   => wp_create_nonce( 'refresh_order_ratio_nonce' ), // Nonce creation
    88                 ]
    89             );
    90        
    91     }
    92 
    93     /**
    94      * Add BD Courier menu in WordPress Admin.
    95      */
    96     public function add_bd_courier_menu() {
    97         add_menu_page(
    98             'Courier Search',         // Page title
    99             'Courier Search',         // Menu title
    100             'manage_options',         // Capability
    101             'bd-courier-search',      // Menu slug
    102             [$this, 'render_search_page'], // Callback function
    103             'dashicons-search',       // Icon
    104             25                        // Position
    105         );
    106     }
    107 
    108     /**
    109      * Render the courier search page in the admin area.
    110      */
    111     public function render_search_page() {
    112         ?>
    113         <div id="courier-search-container" style="max-width: 600px; margin: 20px auto; padding: 20px; background-color: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">
    114             <form id="bdcourier-search-form" method="post" style="margin-bottom: 20px; text-align: center; margin-top: 20px;">
    115                 <?php wp_nonce_field( 'bdcourier_search_nonce_action', 'bdcourier_search_nonce_field' ); ?>
    116                 <input type="text" id="phone" name="phone" placeholder="Enter Phone Number" required style="padding: 10px; width: 70%; border: 1px solid #ddd; border-radius: 5px; display: inline-block; margin-right: 10px;">
    117                 <button type="submit" style="padding: 10px 20px; background-color: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer; display: inline-block;">Search</button>
    118             </form>
    119             <div id="courier-search-result" style="max-width: 100%; margin-top: 20px;"></div>
    120         </div>
    121         <?php
    122     }
    123 
    124     /**
    125      * Add BD Courier settings page under WooCommerce.
    126      */
    127     public function add_bd_courier_settings_page() {
    128         add_menu_page(
    129             'BD Courier Settings',  // Page title
    130             'BD Courier Settings',  // Menu title
    131             'manage_options',       // Capability
    132             'bd-courier-settings',  // Menu slug
    133             [$this, 'render_settings_page'], // Callback function
    134             'dashicons-admin-generic', // Icon
    135             56                        // Position
    136         );
    137     }
    138 
    139     /**
    140      * Render the settings page.
    141      */
    142     public function render_settings_page() {
    143         ?>
    144         <div class="wrap">
    145             <h1>BD Courier Settings</h1>
    146             <form method="post" action="options.php">
    147                 <?php
    148                 settings_fields('bd_courier_settings_group');
    149                 do_settings_sections('bd-courier-settings');
    150                 submit_button();
    151                 ?>
    152             </form>
    153         </div>
    154         <?php
    155     }
    156 
    157     /**
    158      * Register the BD Courier settings.
    159      */
    160     public function register_bd_courier_settings() {
    161         register_setting('bd_courier_settings_group', 'bd_courier_api_token');
    162 
    163         add_settings_section(
    164             'bd_courier_settings_section',
    165             'API Settings',
    166             null,
    167             'bd-courier-settings'
    168         );
    169 
    170         add_settings_field(
    171             'bd_courier_api_token',
    172             'API Token',
    173             [$this, 'render_api_token_field'],
    174             'bd-courier-settings',
    175             'bd_courier_settings_section'
    176         );
    177     }
    178 
    179     /**
    180      * Render the API token input field.
    181      */
    182     public function render_api_token_field() {
    183         $api_token = get_option('bd_courier_api_token');
    184         echo '<input type="text" name="bd_courier_api_token" value="' . esc_attr($api_token) . '" class="regular-text" />';
    185     }
    186 
    187     /**
    188      * Display the search form via shortcode.
    189      */
    190     public function display_search_form() {
    191         ob_start();
    192         ?>
    193         <form id="bdcourier-search-form" method="post" style="margin-bottom: 20px;">
    194             <?php wp_nonce_field( 'bdcourier_search_nonce_action', 'bdcourier_search_nonce_field' ); ?>
    195             <input type="text" id="phone" name="phone" placeholder="Enter Phone Number" required style="padding: 10px; width: 300px; border: 1px solid #ddd;">
    196             <button type="submit" style="padding: 10px 20px; background-color: #28a745; color: white; border: none; cursor: pointer;">Search</button>
    197         </form>
    198         <div id="courier-search-result"></div>
    199         <?php
    200         return ob_get_clean();
    201     }
    202 
    203     /**
    204      * Enqueue frontend-side scripts for handling search form Ajax requests.
    205      */
    206     public function enqueue_search_script() {
    207         wp_enqueue_script('jquery');
    208         wp_enqueue_script(
    209             'bdcourier-search-ajax',
    210             plugin_dir_url(__FILE__) . 'bdcourier-search-ajax.js',
    211             ['jquery'],
    212             null,
    213             true
    214         );
    215         wp_localize_script(
    216             'bdcourier-search-ajax',
    217             'bdcourierSearchAjax',
    218             [
    219                 'ajaxurl' => admin_url('admin-ajax.php'),
    220                 'nonce'   => wp_create_nonce('bdcourier_search_nonce'), // Security nonce
    221             ]
    222         );
    223     }
    224 
    225     /**
    226      * Handle the Ajax request and verify nonce.
    227      */
    228     public function search_courier_data() {
    229     // Verify the nonce
    230     if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'bdcourier_search_nonce' ) ) {
    231         wp_send_json_error( esc_html__( 'Invalid nonce.', 'bd-courier-order-ratio-checker' ) );
    232         return;
    233     }
    234 
    235     // Process the request if nonce is valid
    236     if ( isset( $_POST['phone'] ) && ! empty( $_POST['phone'] ) ) {
    237         $phone = sanitize_text_field( wp_unslash( $_POST['phone'] ) );
    238     } else {
    239         wp_send_json_error( esc_html__( 'Phone number is required.', 'bd-courier-order-ratio-checker' ) );
    240     }
    241 
    242     $courier_data = $this->fetch_order_ratio_from_api( $phone );
    243 
    244     if ( $courier_data ) {
    245         ob_start();
    246         $this->display_courier_data( $courier_data );
    247         $table_html = ob_get_clean();
    248         wp_send_json_success( [ 'table' => $table_html ] );
    249     } else {
    250         wp_send_json_error( esc_html__( 'Failed to fetch data from API.', 'bd-courier-order-ratio-checker' ) );
    251     }
    252 }
    253 
    254 
    255     /**
    256      * Display courier data in table format with a summary row and progress bar.
    257      */
    258     private function display_courier_data($courier_data) {
    259     if (!$courier_data || !is_array($courier_data)) {
    260         return;
    261     }
    262 
    263     // Start table HTML
    264     echo '<div style="margin-top:20px;">';
    265     echo '<table style="width:100%; border-collapse: collapse; margin-bottom: 20px;">';
    266     echo '<thead>';
    267     echo '<tr style="background-color:#f2f2f2;">';
    268     echo '<th style="padding:10px; text-align:left;">Courier</th>';
    269     echo '<th style="padding:10px; text-align:left;">Total</th>';
    270     echo '<th style="padding:10px; text-align:left;">Success</th>';
    271     echo '<th style="padding:10px; text-align:left;">Cancel</th>';
    272     echo '</tr>';
    273     echo '</thead>';
    274     echo '<tbody>';
    275 
    276     foreach ($courier_data as $courier => $data) {
    277         if ($courier !== 'summary' && is_array($data)) {
    278             $total_parcel = isset($data['total_parcel']) ? $data['total_parcel'] : 'N/A';
    279             $success_parcel = isset($data['success_parcel']) ? $data['success_parcel'] : 'N/A';
    280             $cancel_parcel = isset($data['total_parcel']) && isset($data['success_parcel']) ? $total_parcel - $success_parcel : 'N/A';
    281 
    282             echo '<tr>';
    283             echo '<td style="padding:10px; border: 1px solid #ddd;">' . esc_html( ucfirst($courier) ) . '</td>';
    284             echo '<td style="padding:10px; border: 1px solid #ddd;">' . esc_html( $total_parcel ) . '</td>';
    285             echo '<td style="padding:10px; border: 1px solid #ddd;">' . esc_html( $success_parcel ) . '</td>';
    286             echo '<td style="padding:10px; border: 1px solid #ddd;">' . esc_html( $cancel_parcel ) . '</td>';
    287             echo '</tr>';
    288         }
    289     }
    290 
    291     echo '</tbody>';
    292     echo '</table>';
    293 
    294     // Summary row
    295     if (isset($courier_data['summary']) && is_array($courier_data['summary'])) {
    296         $total_parcel = isset($courier_data['summary']['total_parcel']) ? $courier_data['summary']['total_parcel'] : 'N/A';
    297         $success_parcel = isset($courier_data['summary']['success_parcel']) ? $courier_data['summary']['success_parcel'] : 'N/A';
    298         $success_ratio = isset($courier_data['summary']['success_ratio']) ? $courier_data['summary']['success_ratio'] : 0;
    299         $cancel_ratio = $total_parcel > 0 ? 100 - $success_ratio : 0;
    300 
    301         // Styling for pills
    302         $pill_style = 'display: inline-block; padding: 10px 20px; border-radius: 50px; color: white; font-weight: bold; margin-right: 10px;';
    303 
    304         // Summary pills display
    305         echo '<div style="margin-top: 20px;">';
    306 
    307         // Total Parcels Pill (neutral color)
    308         echo '<span style="' . esc_attr( $pill_style ) . ' background-color: #6c757d;">Total : ' . esc_html( $total_parcel ) . '</span>';
    309 
    310         // Success Parcels Pill (green)
    311         echo '<span style="' . esc_attr( $pill_style ) . ' background-color: #28a745;">Success : ' . esc_html( $success_parcel ) . '</span>';
    312 
    313         // Cancel Parcels Pill (red)
    314         echo '<span style="' . esc_attr( $pill_style ) . ' background-color: #dc3545;">Cancel : ' . esc_html( $total_parcel - $success_parcel ) . '</span>';
    315 
    316         // Progress bar for Success/Cancel ratio
    317         echo '<div style="background-color:#f3f3f3; border-radius: 5px; width: 100%; height: 20px; margin-top: 20px; position: relative;">';
    318 
    319         // Only show the success bar if the success ratio is greater than zero
    320         if ($success_ratio > 0) {
    321             echo '<div style="width:' . esc_attr( $success_ratio ) . '%; background-color:#28a745; height: 100%; position: absolute; left: 0;"></div>';
    322         }
    323 
    324         // Only show the cancel bar if the cancel ratio is greater than zero
    325         if ($cancel_ratio > 0) {
    326             echo '<div style="width:' . esc_attr( $cancel_ratio ) . '%; background-color:#dc3545; height: 100%; position: absolute; right: 0;"></div>';
    327         }
    328 
    329         // Only show the text if both success and cancel ratios are greater than zero
    330         if ($success_ratio > 0 || $cancel_ratio > 0) {
    331             echo '<span style="position: absolute; width: 100%; text-align: center; line-height: 20px; color: #fff; font-weight: bold;">' . esc_html( $success_ratio ) . '% Success / ' . esc_html( $cancel_ratio ) . '% Cancel</span>';
    332         }
    333 
    334         echo '</div>'; // End of the progress bar div
    335         echo '</div>';
    336     }
    337 
    338     echo '</div>';
    339 }
    340 
    341     /**
    342      * Fetch courier data from the remote API.
    343      */
    344     private function fetch_order_ratio_from_api($phone) {
    345         // Get the API token from settings
    346         $api_token = get_option('bd_courier_api_token');
    347 
    348         // URL for the API
    349         $url = 'https://bdcourier.com/api/courier-check?phone=' . urlencode($phone);
    350 
    351         // Set headers for the API request
    352         $headers = [
    353             'Authorization' => 'Bearer ' . esc_attr($api_token),
    354             'Content-Type'  => 'application/json',
    355         ];
    356 
    357         // Make the POST request using wp_remote_post with timeout and error handling
    358         $response = wp_remote_post($url, [
    359             'headers' => $headers,
    360             'timeout' => 100,
    361         ]);
    362 
    363         // Handle any WP errors during the API call
    364         if (is_wp_error($response)) {
    365             $error_message = $response->get_error_message();
    366             error_log("API request failed: $error_message");
    367             return null;
    368         }
    369 
    370         // Retrieve and decode the body of the response
    371         $body = wp_remote_retrieve_body($response);
    372         $data = json_decode($body, true);
    373 
    374         // Check if the response body is empty or invalid JSON
    375         if (empty($body) || is_null($data)) {
    376             error_log("Invalid API response: " . $body);
    377             return null;
    378         }
    379 
    380         // Return the courier data if it exists, otherwise return null
    381         return isset($data['courierData']) ? $data['courierData'] : null;
    382     }
    383 
    384     // Refresh courier data with nonce verification
    385     public function refresh_courier_data() {
    386         // Verify nonce
    387         if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'refresh_order_ratio_nonce' ) ) {
    388             wp_send_json_error( esc_html__( 'Invalid nonce.', 'bd-courier-order-ratio-checker' ) );
    389             return;
    390         }
    391 
    392         if ( isset( $_POST['order_id'] ) && ! empty( $_POST['order_id'] ) ) {
    393             $order_id = intval( wp_unslash( $_POST['order_id'] ) );
    394         } else {
    395             wp_send_json_error( esc_html__( 'Invalid order ID.', 'bd-courier-order-ratio-checker' ) );
    396         }
    397 
    398         $order = wc_get_order( $order_id );
    399         if ( ! $order ) {
    400             wp_send_json_error( esc_html__( 'Order not found.', 'bd-courier-order-ratio-checker' ) );
    401         }
    402 
    403         $phone = $order->get_billing_phone();
    404         if ( ! $phone ) {
    405             wp_send_json_error( esc_html__( 'No phone number found.', 'bd-courier-order-ratio-checker' ) );
    406         }
    407 
    408         $courier_data = $this->fetch_order_ratio_from_api( $phone );
    409         if ( $courier_data ) {
    410             update_post_meta( $order_id, '_courier_data', $courier_data );
    411 
    412             ob_start();
    413             $this->display_courier_data( $courier_data );
    414             $table_html = ob_get_clean();
    415 
    416             wp_send_json_success( [ 'table' => $table_html ] );
    417         } else {
    418             wp_send_json_error( esc_html__( 'Failed to fetch courier data.', 'bd-courier-order-ratio-checker' ) );
    419         }
    420     }
    421 
    422     public function display_order_ratio_in_admin($order) {
    423         // Get the customer phone number from the billing data
    424         $customer_phone = $order->get_billing_phone();
    425 
    426         if (!$customer_phone) {
    427             echo '<p style="color: red;">No phone number found for this order.</p>';
    428             return;
    429         }
    430 
    431         // Check if courier data already exists in the order meta
    432         $courier_data = get_post_meta($order->get_id(), '_courier_data', true);
    433 
    434         if (!$courier_data) {
    435             // Fetch courier data from API if not already stored
    436             $courier_data = $this->fetch_order_ratio_from_api($customer_phone);
    437             if ($courier_data) {
    438                 update_post_meta($order->get_id(), '_courier_data', $courier_data);
    439             }
    440         }
    441 
    442         if ($courier_data) {
    443             // Display the courier data if it exists
    444             echo '<div id="courier-data-table">';
    445             $this->display_courier_data($courier_data);
    446             echo '</div>';
    447             echo '<button id="refresh-courier-data" data-order-id="' . esc_attr($order->get_id()) . '" class="button" style="margin-top: 10px; background-color: #28a745; color: white; border: none; padding: 10px; cursor: pointer;">Refresh Courier Data</button>';
    448         } else {
    449             echo '<p style="color: red;">Failed to fetch courier data.</p>';
    450         }
    451     }
    452 }
     18include 'lib/class.OrderRatioChecker.php';
    45319
    45420// Initialize the plugin
    455 new Order_Ratio_Checker();
     21new OrderRatioChecker();
  • bd-courier-order-ratio-checker/trunk/readme.txt

    r3163421 r3173906  
    55Requires at least: 6.0
    66Tested up to: 6.6.2
    7 Stable tag: 1.8
     7Stable tag: 1.9
    88Requires PHP: 7.4
    99License: GPLv2 or later
Note: See TracChangeset for help on using the changeset viewer.