Plugin Directory

Changeset 3251356


Ignore:
Timestamp:
03/05/2025 10:31:23 PM (13 months ago)
Author:
marknokes
Message:

2.4.6

  • Feature: Allow applying different tax rates to woocommerce order based on paypal plan definition
  • Bugfix: Max 20 paypal plans appearing in admin area
  • Improvement: Remove default tax_class from order product when tax inclusive
  • Improvement: Refactor Plan class
Location:
subscriptions-for-woo
Files:
44 added
10 edited

Legend:

Unmodified
Added
Removed
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-ajax-actions.php

    r3249341 r3251356  
    33namespace PPSFWOO;
    44
    5 use PPSFWOO\Subscriber,
     5use PPSFWOO\PluginMain,
     6    PPSFWOO\Subscriber,
    67    PPSFWOO\Exception;
    78
     
    5051
    5152            // phpcs:ignore WordPress.Security.NonceVerification.Missing
    52             $Plan = isset($_POST['product_id']) ? new Plan('product_id', absint($_POST['product_id'])): NULL;
     53            $product_id = isset($_POST['product_id']) ? absint($_POST['product_id']): NULL;
     54
     55            $PluginMain = PluginMain::get_instance();
     56
     57            $plan_id = get_post_meta($product_id, "{$PluginMain->env['env']}_ppsfwoo_plan_id", true) ?? NULL;
     58
     59            $Plan = isset($product_id) ? new Plan($plan_id): NULL;
    5360
    5461            if(isset($Plan) && $Plan->id) {
    55 
    56                 $PluginMain = PluginMain::get_instance();
    5762
    5863                $response = [
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-database.php

    r3248728 r3251356  
    9898        }
    9999
    100         if (version_compare($installed_version, '2.4.4', '<')) {
    101 
    102             set_transient('ppsfwoo_refresh_plans_ran', true, 10);
     100        if (version_compare($installed_version, '2.4.6', '<')) {
    103101
    104102            AjaxActionsPriv::refresh_plans();
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-order.php

    r3249734 r3251356  
    1919    private static $line_item_price = 0;
    2020
     21    private static $Subscriber = NULL;
     22
    2123    public function __construct()
    2224    {
     
    4749    }
    4850
    49     public static function get_address(Subscriber $Subscriber)
     51    public static function get_address()
    5052    {
    5153        return [
    52             'first_name' => $Subscriber->first_name,
    53             'last_name'  => $Subscriber->last_name,
     54            'first_name' => self::$Subscriber->first_name,
     55            'last_name'  => self::$Subscriber->last_name,
    5456            'company'    => '',
    55             'email'      => $Subscriber->email,
     57            'email'      => self::$Subscriber->email,
    5658            'phone'      => '',
    57             'address_1'  => $Subscriber->address_line_1,
    58             'address_2'  => $Subscriber->address_line_2,
    59             'city'       => $Subscriber->city,
    60             'state'      => $Subscriber->state,
    61             'postcode'   => $Subscriber->postal_code,
    62             'country'    => $Subscriber->country_code
     59            'address_1'  => self::$Subscriber->address_line_1,
     60            'address_2'  => self::$Subscriber->address_line_2,
     61            'city'       => self::$Subscriber->city,
     62            'state'      => self::$Subscriber->state,
     63            'postcode'   => self::$Subscriber->postal_code,
     64            'country'    => self::$Subscriber->country_code
    6365        ];
    6466    }
     
    122124    }
    123125
    124     private static function create_fee($name, $amount)
    125     {
    126         $fee = new \WC_Order_Item_Fee();
    127 
    128         $fee->set_name($name);
    129 
    130         $fee->set_amount($amount);
    131 
    132         $fee->set_total($amount);
    133 
    134         // Need this here because the loop below over $order->get_items() does not contain fee(s)
    135         if(self::$tax_rate_data['tax_rate'] !== 0 && empty(self::$tax_rate_data['inclusive'])) {
    136                
    137             $fee->set_tax_class(self::$tax_rate_data['tax_rate_slug']);
    138 
    139         }
    140 
    141         return $fee;
    142     }
    143 
    144     private static function parse_order_items($order, $Subscriber)
     126    private static function parse_billing_cycles()
    145127    {
    146128        $items = [];
    147129
    148         $payment_preferences = $Subscriber->plan->get_payment_preferences();
    149 
    150         $plan_id = $Subscriber->get_plan_id();
    151 
    152         $product_id = Product::get_product_id_by_plan_id($plan_id);
    153 
    154         $product = wc_get_product($product_id);
    155 
    156         foreach ($Subscriber->plan->get_billing_cycles() as $cycle)
     130        foreach (self::$Subscriber->plan->get_billing_cycles() as $cycle)
    157131        {
    158132            $sequence = intval($cycle['sequence']);
     
    191165        }
    192166
    193         if(isset($payment_preferences['setup_fee']['value']) && $payment_preferences['setup_fee']['value'] > 0) {
    194 
    195             $fee_amount = floatval($payment_preferences['setup_fee']['value']);
    196 
    197             $fee = self::create_fee('One-time setup fee', $fee_amount);
     167        return $items;
     168    }
     169
     170    private static function parse_order_items($order)
     171    {
     172        $payment_preferences = self::$Subscriber->plan->get_payment_preferences() ?? [];
     173
     174        $plan_id = self::$Subscriber->get_plan_id();
     175
     176        $product_id = Product::get_product_id_by_plan_id($plan_id);
     177
     178        $product = wc_get_product($product_id);
     179
     180        $items = self::parse_billing_cycles();
     181
     182        if(
     183            isset($payment_preferences['setup_fee']['value'])
     184            && $payment_preferences['setup_fee']['value'] > 0
     185        ) {
     186
     187            $fee = new \WC_Order_Item_Fee();
     188           
     189            $fee->set_name('One-time setup fee');
     190
     191            $fee->set_total(floatval($payment_preferences['setup_fee']['value']));
    198192
    199193            array_push($items, $fee);
     
    201195        }
    202196
     197        // handle adding product to order first & seperately
    203198        $product->set_price(self::$line_item_price);
    204199
    205200        $order->add_product($product, self::$quantity);
    206201
    207         foreach ($order->get_items() as $item_id => $item)
     202        foreach ($order->get_items() as $item)
    208203        {
    209204            $product = $item->get_product();
     
    219214            }
    220215
    221             if(self::$tax_rate_data['tax_rate'] !== 0) {
    222 
    223                 if(empty(self::$tax_rate_data['inclusive'])) {
    224 
    225                     $item->set_tax_class(self::$tax_rate_data['tax_rate_slug']);
    226 
    227                 } else {
    228 
    229                     $item->set_tax_class("");
    230 
    231                 }
    232             }
    233            
    234             $item->save();
    235         }
    236 
     216            self::set_taxes($item);
     217        }
     218
     219        // add additional line items to order
    237220        foreach($items as $sequence => $item)
    238221        {
     222            self::set_taxes($item);
     223
    239224            $order->add_item($item);
    240225        }
     226    }
     227
     228    private static function set_taxes($item)
     229    {
     230        $taxes = \WC_Tax::get_rates_for_tax_class(self::$tax_rate_data['tax_rate_slug']);
     231
     232        $found_rate = NULL;
     233
     234        if(self::$tax_rate_data['tax_rate'] === 0 || !empty(self::$tax_rate_data['inclusive']) || !$taxes)
     235        {
     236            $item->set_tax_class("");
     237
     238            return;
     239        }
     240
     241        foreach ($taxes as $tax_rate_object)
     242        {
     243            if(self::$tax_rate_data['tax_rate'] === $tax_rate_object->tax_rate) {
     244
     245                $found_rate = $tax_rate_object;
     246
     247                break;
     248
     249            }
     250        }
     251
     252        if(!isset($found_rate)) {
     253
     254            $item->set_tax_class("");
     255
     256            return;
     257
     258        }
     259
     260        $tax_rates[ $found_rate->tax_rate_id ] = [
     261            'rate'     => (float) $found_rate->tax_rate,
     262            'label'    => $found_rate->tax_rate_name,
     263            'shipping' => $found_rate->tax_rate_shipping ? 'yes' : 'no',
     264            'compound' => $found_rate->tax_rate_compound ? 'yes' : 'no',
     265        ];
     266
     267        $get_subtotal = method_exists($item, 'get_subtotal') ? 'get_subtotal': 'get_total';
     268
     269        $taxes = \WC_Tax::calc_tax($item->get_total(), $tax_rates, false);
     270
     271        $subtotal_taxes = \WC_Tax::calc_tax($item->$get_subtotal(), $tax_rates, false);
     272
     273        $item->set_tax_class(self::$tax_rate_data['tax_rate_slug']);
     274       
     275        $item->set_taxes([
     276            'subtotal' => $subtotal_taxes,
     277            'total'    => $taxes,
     278        ]);
    241279    }
    242280
    243281    public static function insert(Subscriber $Subscriber)
    244282    {   
    245         self::$tax_rate_data = $Subscriber->plan->get_tax_rate_data();
    246 
    247         self::$quantity = $Subscriber->subscription->quantity ?? self::$quantity;
     283        self::$Subscriber = $Subscriber;
     284
     285        self::$tax_rate_data = self::$Subscriber->plan->get_tax_rate_data();
     286
     287        self::$quantity = self::$Subscriber->subscription->quantity ?? self::$quantity;
    248288
    249289        $order = wc_create_order();
    250290
    251         $order->set_customer_id($Subscriber->user_id);
    252 
    253         self::parse_order_items($order, $Subscriber);
    254 
    255         $order->set_address(self::get_address($Subscriber), 'billing');
    256 
    257         $order->set_address(self::get_address($Subscriber), 'shipping');
     291        $order->set_customer_id(self::$Subscriber->user_id);
     292
     293        self::parse_order_items($order);
     294
     295        $order->set_address(self::get_address(), 'billing');
     296
     297        $order->set_address(self::get_address(), 'shipping');
    258298
    259299        $order->set_payment_method('paypal');
     
    263303        $order->calculate_shipping();
    264304
    265         $order->calculate_totals();
     305        $order->update_taxes();
     306
     307        $order->calculate_totals(false);
    266308
    267309        $order->set_discount_total(0);
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-plan.php

    r3249341 r3251356  
    66    PPSFWOO\PluginMain;
    77
    8 class Plan extends PluginMain
     8class Plan
    99{
    10     public $id,
     10    public $env,
     11           $id,
    1112           $frequency,
     13           $price,
     14           $product_name,
    1215           $version,
    1316           $product_id,
     
    2528           $description;
    2629
    27     public function __construct($construct_by = "", $value = NULL)
     30    public function __construct($id = NULL)
    2831    {
    29         parent::__construct();
    30 
    31         switch ($construct_by)
    32         {
    33             case 'plan_id':
    34 
    35                 $this->id = $value;
    36 
    37                 break;
    38 
    39             case 'product_id':
    40 
    41                 $this->id = $this->get_id_by_product_id($value);
    42 
    43                 break;
    44         }
    45 
    46         if(isset($this->id)) {
    47 
    48             foreach($this->get_cached_response() as $response_key => $response_item)
     32        $PluginMain = PluginMain::get_instance();
     33
     34        $this->env = $PluginMain->env['env'];
     35
     36        $this->id = $id;
     37
     38        $plan_data = $PluginMain->ppsfwoo_plans[$this->env][$this->id] ?? NULL;
     39
     40        if(isset($this->id, $plan_data)) {
     41
     42            foreach($plan_data as $response_key => $response_item)
    4943            {
    5044
     
    5347            }
    5448           
    55             $this->frequency = self::get_from_response_billing_cycles('frequency', $this->billing_cycles);
     49            $this->frequency = $this->get_from_billing_cycles('frequency');
     50
     51            $this->price = $this->get_from_billing_cycles('price');
     52
     53            $this->product_name = $plan_data['product_name'] ?? "";
    5654        }
    5755    }
    5856
    59     public function get_cached_response()
    60     {
    61         return $this->ppsfwoo_plans[$this->env['env']][$this->id]['response'] ?? NULL;
    62     }
    63 
    64     public function get_billing_cycles()
    65     {
    66         return $this->billing_cycles;
    67     }
    68 
    69     private function get_id_by_product_id($product_id)
    70     {
    71         return get_post_meta($product_id, "{$this->env['env']}_ppsfwoo_plan_id", true) ?? "";
    72     }
    73 
    74     public static function get_from_response_billing_cycles($find, $response = NULL)
    75     {
    76         $billing_cycles = $response['billing_cycles'] ?? $response ?? [];
     57    public function __call($name, $arguments)
     58    {
     59        if (strpos($name, 'get_') === 0) {
     60
     61            $property = lcfirst(substr($name, 4));
     62
     63            if (property_exists($this, $property)) {
     64
     65                return $this->$property;
     66
     67            }
     68        }
     69
     70        throw new \BadMethodCallException("Method $name does not exist.");
     71    }
     72
     73    private function get_from_billing_cycles($find, $response = NULL)
     74    {
     75        $billing_cycles = $this->billing_cycles ?? $response['billing_cycles'] ?? $response ?? [];
    7776       
    7877        foreach ($billing_cycles as $cycle)
     
    114113        $response = ['error' => 'An unexpected error occurred.'];
    115114
    116         if(!isset($_POST['nonce'], $_POST['plan_id'], $_POST['paypal_action']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'modify_plan')) {
     115        if(
     116            !isset($_POST['nonce'], $_POST['plan_id'], $_POST['paypal_action'])
     117            || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'modify_plan')
     118        ) {
    117119
    118120            return ['error' => 'Security check failed.'];
     
    147149    public function refresh_all()
    148150    {
     151        $PluginMain = PluginMain::get_instance();
     152
    149153        $plans = [];
    150154
    151         $plan_data = PayPal::request(
    152             PayPal::EP_PLANS,
    153             ['page_size' => 20],
    154             "GET",
    155             ['Prefer' => 'return=representation']
    156         );
    157 
    158         if($plan_data && isset($plan_data['response']['plans'])) {
    159 
    160             $products = [];
    161 
    162             foreach($plan_data['response']['plans'] as $plan)
    163             {
    164                 if($this->ppsfwoo_hide_inactive_plans && "ACTIVE" !== $plan['status']) {
    165 
    166                     continue;
    167 
     155        $page = 1;
     156
     157        do {
     158
     159            $plan_data = PayPal::request(
     160                PayPal::EP_PLANS,
     161                ['page_size' => 20, 'page' => $page],
     162                "GET",
     163                ['Prefer' => 'return=representation']
     164            );
     165
     166            if($plan_data
     167                && isset($plan_data['response']['plans'])
     168                && count($plan_data['response']['plans']) > 0
     169            ) {
     170
     171                $products = [];
     172
     173                foreach($plan_data['response']['plans'] as $plan)
     174                {
     175                    if($PluginMain->ppsfwoo_hide_inactive_plans && "ACTIVE" !== $plan['status']) {
     176
     177                        continue;
     178
     179                    }
     180
     181                    if(!in_array($plan['product_id'], array_keys($products))) {
     182                   
     183                        $product_data = PayPal::request(PayPal::EP_PRODUCTS . $plan['product_id']);
     184
     185                        $product_name = $product_data['response']['name'];
     186
     187                        $products[$plan['product_id']] = $product_name;
     188
     189                    } else {
     190
     191                        $product_name = $products[$plan['product_id']];
     192                    }
     193
     194                    if(isset($plan['taxes'])) {
     195
     196                        $tax_rate_id = $this->insert_tax_rate(floatval($plan['taxes']['percentage']));
     197
     198                    }
     199
     200                    $plan['product_name'] = $product_name;
     201
     202                    $plans[$plan['id']] = $plan;
    168203                }
    169204
    170                 if(!in_array($plan['product_id'], array_keys($products))) {
     205                $page++;
     206
     207            } else {
    171208               
    172                     $product_data = PayPal::request(PayPal::EP_PRODUCTS . $plan['product_id']);
    173 
    174                     $product_name = $product_data['response']['name'];
    175 
    176                     $products[$plan['product_id']] = $product_name;
    177 
    178                 } else {
    179 
    180                     $product_name = $products[$plan['product_id']];
    181                 }
    182 
    183                 if(isset($plan['taxes'])) {
    184 
    185                     $tax_rate_id = $this->insert_tax_rate(floatval($plan['taxes']['percentage']));
    186 
    187                 }
    188 
    189                 $plans[$plan['id']] = [
    190                     'plan_name'     => $plan['name'],
    191                     'product_name'  => $product_name,
    192                     'frequency'     => self::get_from_response_billing_cycles('frequency', $plan),
    193                     'status'        => $plan['status'],
    194                     'price'         => self::get_from_response_billing_cycles('price', $plan),
    195                     'response'      => $plan
    196                 ];
    197             }
    198 
    199             uasort($plans, function ($a, $b) {
    200                 return strcmp($a['status'], $b['status']);
    201             });
    202        
    203             $env = $this->env['env'];
    204 
    205             update_option('ppsfwoo_plans', [
    206                 $env => $plans
    207             ]);
    208 
    209         }
     209                break;
     210
     211            }
     212
     213        } while (true);
     214
     215        uasort($plans, function ($a, $b) {
     216            return strcmp($a['status'], $b['status']);
     217        });
     218   
     219        $env = $this->env;
     220
     221        update_option('ppsfwoo_plans', [
     222            $env => $plans
     223        ]);
    210224
    211225        return $plans;
    212226    }
    213227
    214     public function get_payment_preferences()
    215     {
    216         $cached_response = $this->get_cached_response();
    217 
    218         return isset($cached_response, $cached_response['payment_preferences']) ? $cached_response['payment_preferences']: [];
    219     }
    220 
    221228    public function get_tax_rate_data()
    222229    {
    223         $class = self::plugin_data('Name');
     230        $class = PluginMain::get_instance()::plugin_data('Name');
    224231
    225232        $slug = strtolower(str_replace(' ', '-', $class));
     
    229236        $inclusive = NULL;
    230237
    231         if($cached_response = $this->get_cached_response()) {
    232 
    233             if(isset($cached_response['taxes'])) {
    234 
    235                 $tax_rate = floatval($cached_response['taxes']['percentage']) ?? 0;
    236 
    237                 $inclusive = !empty($cached_response['taxes']['inclusive']);
     238        if($taxes = $this->get_taxes()) {
     239
     240            if(isset($taxes)) {
     241
     242                $tax_rate = number_format($taxes['percentage'], 4) ?? 0;
     243
     244                $inclusive = !empty($taxes['inclusive']);
    238245               
    239246            }
     
    249256    }
    250257
    251     public function insert_tax_rate($tax_rate)
     258    private function insert_tax_rate($tax_rate)
    252259    {
    253260        $tax_rate_data = $this->get_tax_rate_data();
     
    302309    }
    303310
    304     public function get_plans()
     311    public static function get_plans()
    305312    {
    306         return $this->ppsfwoo_plans[$this->env['env']] ?? [];
     313        $plan_objects = [];
     314
     315        $PluginMain = PluginMain::get_instance();
     316
     317        $plans = $PluginMain->ppsfwoo_plans[$PluginMain->env['env']] ?? [];
     318
     319        if($plans) {
     320
     321            foreach($plans as $plan_id => $plan)
     322            {
     323
     324                $plan_objects[$plan_id] = new self($plan_id);
     325
     326            }
     327
     328        }
     329
     330        return $plan_objects;
    307331    }
    308332}
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-product.php

    r3248886 r3251356  
    129129                $selected_plan_id = get_post_meta($post->ID, "{$this->env}_ppsfwoo_plan_id", true);
    130130
    131                 $Plan = new Plan();
    132 
    133                 $plans = $Plan->get_plans();
     131                $plans = Plan::get_plans();
    134132
    135133                if($plans && !isset($plans['000'])) {
     
    139137                    $options = "<option value=''>Select a plan [" . $this->env . "]</option>";
    140138
    141                     foreach($plans as $plan_id => $plan_data)
     139                    foreach($plans as $plan_id => $plan)
    142140                    {
    143                         if("ACTIVE" !== $plan_data['status']) {
     141                        if("ACTIVE" !== $plan->status) {
    144142
    145143                            unset($plans[$plan_id]);
     
    149147                            $selected = $selected_plan_id === $plan_id ? 'selected': '';
    150148
    151                             $options .= '<option value="' . esc_attr($plan_id) . '" ' . $selected . ' data-price="' . esc_attr($formatter->formatCurrency($plan_data['price'], 'USD')) . '">' . esc_html("{$plan_data['plan_name']} [{$plan_data['product_name']}] [{$plan_data['frequency']}]") . '</option>';
     149                            $options .= '<option value="' . esc_attr($plan_id) . '" ' . $selected . ' data-price="' . esc_attr($formatter->formatCurrency($plan->price, 'USD')) . '">' . esc_html("{$plan->name} [{$plan->product_name}] [{$plan->frequency}]") . '</option>';
    152150
    153151                        }
     
    272270        }
    273271
    274         $Plan = new Plan('product_id', $product_id);
     272        $plan_id = get_post_meta($product_id, "{$this->PluginMain->env['env']}_ppsfwoo_plan_id", true) ?? NULL;
     273
     274        $Plan = new Plan($plan_id);
    275275
    276276        if ($Plan->frequency) {
  • subscriptions-for-woo/trunk/classes/PPSFWOO/class-ppsfwoo-subscriber.php

    r3248728 r3251356  
    3434        $this->subscription = (object) $subscription[$type];
    3535
    36         $this->plan = new Plan('plan_id', $this->get_plan_id());
     36        $this->plan = new Plan($this->get_plan_id());
    3737
    3838        $this->subscription->last_payment = !empty($this->subscription->billing_info['last_payment']['time'])
  • subscriptions-for-woo/trunk/readme.txt

    r3248886 r3251356  
    44License: GPLv2 or later
    55License URI: http://www.gnu.org/licenses/gpl-2.0.html
    6 Stable tag: 2.4.5
    7 WC tested up to: 9.7.0
     6Stable tag: 2.4.6
     7WC tested up to: 9.7.1
    88Requires at least: 6.4.3
    99Tested up to: 6.7.2
     
    106106== Changelog ==
    107107
     108= 2.4.6 =
     109* Feature: Allow applying different tax rates to woocommerce order based on paypal plan definition
     110* Bugfix: Max 20 paypal plans appearing in admin area
     111* Improvement: Remove default tax_class from order product when tax inclusive
     112* Improvement: Refactor Plan class
     113
    108114= 2.4.5 =
    109115* Bugfix: general tab on product page not displaying
  • subscriptions-for-woo/trunk/subscriptions-for-woo.php

    r3248886 r3251356  
    88 * License: GPLv2 or later
    99 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
    10  * Version: 2.4.5
     10 * Version: 2.4.6
    1111 * WC requires at least: 8.6.0
    12  * WC tested up to: 9.7.0
     12 * WC tested up to: 9.7.1
    1313 * Requires at least: 6.4.3
    1414 * Tested up to: 6.7.2
  • subscriptions-for-woo/trunk/templates/tab-content/tab-plans.php

    r3126531 r3251356  
    1010<?php
    1111
    12 $Plan = new Plan();
    13 
    14 $plans = $Plan->get_plans();
     12$plans = Plan::get_plans();
    1513
    1614if(sizeof($plans)) {
  • subscriptions-for-woo/trunk/templates/table-plans.php

    r3248728 r3251356  
    1313    </tr>
    1414    <?php
    15     foreach ($plans as $plan_id => $plan_data)
     15    foreach ($plans as $plan_id => $plan)
    1616    {
    17         $plan_active = "ACTIVE" === $plan_data['status'];
     17        $plan_active = "ACTIVE" === $plan->status;
    1818
    1919        $paypal_action = $plan_active ? 'deactivate': 'activate';
     
    2626        <tr class="plan-row">
    2727            <td><a href='<?php echo esc_url($paypal_url); ?>/billing/plans/<?php echo esc_attr($plan_id); ?>' target='_blank'><?php echo esc_html($plan_id); ?></a></td>
    28             <td><?php echo esc_html($plan_data['plan_name']); ?></td>
    29             <td><?php echo esc_html($plan_data['product_name']); ?></td>
    30             <td><?php echo esc_html($plan_data['frequency']); ?></td>
    31             <td><?php echo esc_html($formatter->formatCurrency($plan_data['price'], 'USD')); ?></td>
     28            <td><?php echo esc_html($plan->name); ?></td>
     29            <td><?php echo esc_html($plan->product_name); ?></td>
     30            <td><?php echo esc_html($plan->frequency); ?></td>
     31            <td><?php echo esc_html($formatter->formatCurrency($plan->price, 'USD')); ?></td>
    3232            <td>
    3333                <p class="copy-text"><?php echo esc_url($paypal_url); ?>/webapps/billing/plans/subscribe?plan_id=<?php echo esc_html($plan_id); ?></p>
    3434                <button class="copy-button">Copy to clipboard</button>
    3535            </td>
    36             <td><span class='tooltip status <?php echo esc_attr($status_indicator); ?>'><span class='tooltip-text'><?php echo esc_html($plan_data['status']); ?></span></span></td>
     36            <td><span class='tooltip status <?php echo esc_attr($status_indicator); ?>'><span class='tooltip-text'><?php echo esc_html($plan->status); ?></span></span></td>
    3737            <td><a href='#' class='<?php echo esc_attr($paypal_action); ?>' data-plan-id='<?php echo esc_attr($plan_id); ?>' data-nonce='<?php echo esc_attr(wp_create_nonce('modify_plan')); ?>'><?php echo esc_html(ucfirst($paypal_action)); ?></a></td>
    3838        </tr>
Note: See TracChangeset for help on using the changeset viewer.