# routeapp/2.4.19/includes/class-routeapp-admin-route-fee.php

Route ‑ Shipping Protection, version 2.4.19. 347 lines.

- Page: https://pluginprobe.com/plugins/routeapp/2.4.19/code/includes/class-routeapp-admin-route-fee.php
- Raw: https://pluginprobe.com/plugins/routeapp/2.4.19/raw/includes/class-routeapp-admin-route-fee.php
- Modified: 2026-08-03T15:03:22+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/routeapp/2.4.19/code/includes/class-routeapp-admin-route-fee.php#L10-L20`.

```php
<?php

use Automattic\WooCommerce\Utilities\OrderUtil;

class Routeapp_Admin_Route_Fee {

    const ROUTE_CHARGE_POST_META = '_routeapp_route_charge';
    const ROUTE_PROTECTION_POST_META = '_routeapp_route_protection';

    /**
     * Per-request quote cache keyed by admin cart ref.
     *
     * @var array<string, object|false>
     */
    private $admin_order_quote_cache = array();

    public function __construct()
    {
        if (!is_admin()) {
            return false;
        }
        $this->init();
    }

    public function init()
    {
        add_action('woocommerce_order_item_add_action_buttons', array($this, 'routeapp_custom_admin_button'), 10, 1);
        add_action('woocommerce_new_order_item', array($this, 'recalculate_route_fee'), 10, 1);
        add_action('woocommerce_add_order_tax', array($this, 'recalculate_route_fee'), 10, 1);
        add_action('woocommerce_saved_order_items', array($this, 'recalculate_route_fee'), 10, 1);
        add_action('woocommerce_delete_order_item', array($this, 'recalculate_route_fee'), 10, 1);
    }

    public static function get_route_public_instance(){
        global $routeapp_public;
        return $routeapp_public;
    }

    public function routeapp_custom_admin_button($order)
    {
        echo $this->get_route_fee_button_html($order);
    }

    public function get_route_fee_button_html($order)
    {
        if (!$this->can_show_route_fee_buttons($order)) {
            return '';
        }

        if ($this->has_route_fee_applied($order)) {
            return '<button type="button" id="remove-route-fee" class="button generate-items">' . esc_html__( 'Remove Route Fee', 'routeapp' ) . '</button>';
        }

        if ($this->is_order_eligible_for_route_coverage($order)) {
            return '<button type="button" id="add-route-fee" class="button generate-items">' . esc_html__( 'Add Route Fee', 'routeapp' ) . '</button>';
        }

        return '';
    }

    public function routeapp_refresh_admin_fee_button()
    {
        check_ajax_referer( 'order-item', 'security' );

        if (!isset($_POST['order_id'])) {
            wp_send_json_error('Missing order_id in the request.');
            return;
        }

        $order = wc_get_order(absint($_POST['order_id']));
        if (!$order) {
            wp_send_json_error('Invalid order_id.');
            return;
        }

        wp_send_json_success(array(
            'html' => $this->get_route_fee_button_html($order),
        ));
    }

    private function get_admin_order_cart_ref($order, $cart_total, $cart_items)
    {
        $items_hash = substr(md5(wp_json_encode($cart_items)), 0, 8);

        return 'admin-' . $order->get_id() . '-' . $cart_total . '-' . $items_hash;
    }

    private function get_admin_order_quote_context($order)
    {
        $routeapp_public = self::get_route_public_instance();
        $cart_total = round($routeapp_public->get_cart_subtotal_with_only_shippable_items($order, 'order'), 2);
        $cart_items = $routeapp_public->get_cart_shippable_items($order, 'order');

        return array(
            'total' => $cart_total,
            'items' => $cart_items,
            'ref' => $this->get_admin_order_cart_ref($order, $cart_total, $cart_items),
            'currency' => get_woocommerce_currency(),
            'public' => $routeapp_public,
        );
    }

    private function fetch_admin_order_quote($order)
    {
        $context = $this->get_admin_order_quote_context($order);

        if ($context['total'] <= 0) {
            return false;
        }

        if (array_key_exists($context['ref'], $this->admin_order_quote_cache)) {
            return $this->admin_order_quote_cache[$context['ref']];
        }

        $quote = $context['public']->routeapp_get_quote_from_api(
            $context['ref'],
            $context['total'],
            $context['currency'],
            $context['items']
        );

        $this->admin_order_quote_cache[$context['ref']] = $quote;

        return $quote;
    }

    public function is_order_eligible_for_route_coverage($order)
    {
        if (!$order) {
            return false;
        }

        $routeapp_public = self::get_route_public_instance();
        $route_insurance_quote = $this->fetch_admin_order_quote($order);

        return $this->is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public);
    }

    private function is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public)
    {
        if (!$route_insurance_quote) {
            return false;
        }

        if (!isset($route_insurance_quote->premium->amount) || $route_insurance_quote->premium->amount <= 0) {
            return false;
        }

        return isset($route_insurance_quote->payment_responsible->type)
            && $route_insurance_quote->payment_responsible->type === $routeapp_public->get_allowed_quote_type();
    }

    private function routeapp_handle_admin_fee($order)
    {
        if (!$this->can_add_fee($order)) {
            return false;
        }
        $routeapp_public = self::get_route_public_instance();
        $route_insurance_quote = $this->fetch_admin_order_quote($order);

        $route_insurance_amount = false;
        if ($this->is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public)) {
            $route_insurance_amount = $route_insurance_quote->premium->amount;
        }
        if ($route_insurance_amount > 0) {
            $this->routeapp_create_fee($order, $route_insurance_amount);
            $order->calculate_totals();
            if ($order->save()) {

                $acceptedOrderStatuses = get_option('routeapp_included_order_statuses') ? get_option('routeapp_included_order_statuses') : [];
                $acceptedCanceledStatuses = get_option('routeapp_cancel_order_statuses') ? get_option('routeapp_cancel_order_statuses') : [];

                if ( class_exists('Automattic\WooCommerce\Utilities\OrderUtil')
                    && OrderUtil::custom_orders_table_usage_is_enabled() ) {
                    // HPOS usage is enabled.
                    $order->update_meta_data(self::ROUTE_CHARGE_POST_META, $route_insurance_amount );
                    $order->update_meta_data(self::ROUTE_PROTECTION_POST_META, true );

                    $order->update_meta_data('_routeapp_included_order_statuses', json_encode($acceptedOrderStatuses));
                    $order->update_meta_data( '_routeapp_cancel_order_statuses', json_encode($acceptedCanceledStatuses));

                    $order->save();
                } else {
                    // Traditional CPT-based orders are in use.
                    update_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META, $route_insurance_amount );
                    update_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META, true );

                    update_post_meta( $order->get_id(), '_routeapp_included_order_statuses', json_encode($acceptedOrderStatuses));
                    update_post_meta( $order->get_id(), '_routeapp_cancel_order_statuses', json_encode($acceptedCanceledStatuses));

                }
                return true;
            }
        } else {
            if ($this->has_route_fee_applied($order)) {
                $this->routeapp_remove_route_fee($order);
                $order->calculate_totals();
                $order->save();
            }
        }

        return false;
    }

    private function routeapp_create_fee($order, $fee_amount) {
        $routeapp_public = self::get_route_public_instance();
        if (!$this->has_route_fee_applied($order)) {
            $item_fee = new WC_Order_Item_Fee();
            $item_fee->set_name( Routeapp_Public::ROUTE_LABEL );
            $item_fee->set_tax_class( $routeapp_public->routeapp_get_taxable_class() );
            $item_fee->set_tax_status( $routeapp_public->routeapp_get_fee_taxable() ? 'taxable' : 'none' );
            $item_fee->set_amount( $fee_amount );
            $item_fee->set_total( $fee_amount );
            Routeapp_Public::routeapp_mark_protection_fee_item( $item_fee );
            $order->add_item( $item_fee );
        } else {
            $fees = $this->get_route_fees($order);
            foreach($fees as $fee_id => $fee) {
                if ($fee) {
                    $fee->set_amount($fee_amount);
                    $fee->set_total($fee_amount);
                    Routeapp_Public::routeapp_mark_protection_fee_item( $fee );
                    $fee->save();
                }
            }
        }
    }

    public function routeapp_add_admin_fee()
    {
        check_ajax_referer( 'order-item', 'security' );

        if (!isset($_POST) || !$_POST['order_id']) {
            wp_send_json_error('Missing order_id in the request.');
            return;
        }

        $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0;
        $order = wc_get_order( $order_id );
        if (!$order) {
            wp_send_json_error('Invalid order_id.');
            return;
        }

        $response = $this->routeapp_handle_admin_fee($order);

        if ($response) {
            wp_send_json_success( 'order updated!' );
            return;
        }

        wp_send_json_error('error while adding route fee to the order');
    }

    function routeapp_remove_admin_fee()
    {
        check_ajax_referer( 'order-item', 'security' );

        if (!isset($_POST) || !$_POST['order_id']) {
            wp_send_json_error('Missing order_id in the request.');
            return;
        }

        $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0;
        $order = wc_get_order( $order_id );
        if (!$order) {
            wp_send_json_error('Invalid order_id.');
            return;
        }

        if ($this->has_route_fee_applied($order)) {
            $this->routeapp_remove_route_fee($order);
            $order->calculate_totals();
            $order->save();
        }

        wp_send_json_success('route fee removed from the order');
    }

    private function routeapp_remove_route_fee($order)
    {
        $fees = $this->get_route_fees($order);

        foreach($fees as $fee_id => $fee) {
            if ($fee) {
                wc_delete_order_item($fee_id);
            }
        }

        if ( class_exists('Automattic\WooCommerce\Utilities\OrderUtil')
            && OrderUtil::custom_orders_table_usage_is_enabled() ) {
            $order->delete_meta_data(self::ROUTE_CHARGE_POST_META);
            $order->delete_meta_data(self::ROUTE_PROTECTION_POST_META);
        } else {
            delete_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META );
            delete_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META );
        }
    }

    public function recalculate_route_fee($order_id)
    {
        $order = wc_get_order( $order_id );

        if ($this->has_route_fee_applied($order)) {
            $this->routeapp_handle_admin_fee($order);
        }
    }

    private function get_route_fees($order)
    {
        if (!$order) {
            return [];
        }

        $fees = $order->get_fees();
        $route_fees = [];
        foreach($fees as $fee_id => $fee) {
            if (Routeapp_Public::routeapp_is_route_protection_fee($fee)) {
                $route_fees[$fee_id] = $fee;
            }
        }
        return $route_fees;
    }

    public function can_show_route_fee_buttons($order)
    {
        return $order
            && count($order->get_items()) > 0
            && is_admin()
            && in_array($order->get_status(), array('pending', 'on-hold', 'auto-draft'), true);
    }

    public function can_add_fee($order)
    {
        return $this->can_show_route_fee_buttons($order);
    }

    private function has_route_fee_applied($order)
    {
        $routeFees = $this->get_route_fees($order);
        if (is_array($routeFees) || $routeFees instanceof Countable) {
            return count($routeFees) > 0;
        }
        return false;
    }
}

```
