class-price-category.php (7194B)
1 <?php 2 /** 3 * Price Category Class 4 * 5 * Handles price category data and operations. 6 */ 7 8 if (!defined('ABSPATH')) { 9 exit; 10 } 11 12 class Taler_Price_Category { 13 14 /** 15 * Get all price categories 16 */ 17 public static function get_all() { 18 return get_option('taler_turnstile_price_categories', array()); 19 } 20 21 /** 22 * Get a specific price category by ID 23 */ 24 public static function get($id) { 25 $categories = self::get_all(); 26 return $categories[$id] ?? null; 27 } 28 29 /** 30 * Save a price category 31 */ 32 public static function save($id, $data) { 33 $categories = self::get_all(); 34 $categories[$id] = $data; 35 update_option('taler_turnstile_price_categories', $categories); 36 } 37 38 /** 39 * Delete a price category 40 */ 41 public static function delete($id) { 42 $categories = self::get_all(); 43 if (isset($categories[$id])) { 44 unset($categories[$id]); 45 update_option('taler_turnstile_price_categories', $categories); 46 return true; 47 } 48 return false; 49 } 50 51 /** 52 * Get subscriptions where price is zero (full access) 53 */ 54 public static function get_full_subscriptions($prices) { 55 $subscriptions = array(); 56 57 foreach ($prices as $token_family_slug => $currency_map) { 58 foreach ($currency_map as $currency_code => $price) { 59 if (is_numeric($price) && floatval($price) <= 0.0) { 60 $subscriptions[] = $token_family_slug; 61 break; 62 } 63 } 64 } 65 66 return $subscriptions; 67 } 68 69 /** 70 * Gets a brief hint to display about non-subscriber prices. 71 */ 72 public static function getPriceHint($id) { 73 $category = self::get($id); 74 if (!$category || !isset($category['prices'])) { 75 return __(/* translators: Need to buy a subscription */ 'Not sold individually'); 76 } 77 78 $prices = $category['prices']; 79 $nosub = $prices['%none%']; 80 $rval = NULL; 81 foreach ($nosub as $currency => $price) { 82 if (NULL === $rval) 83 { 84 $rval = "$price $currency"; 85 } 86 else 87 { 88 $rval = "$price $currency, " . $rval; 89 } 90 } 91 return $rval ?? __(/* translators: Need to buy a subscription */ 'Not sold individually'); 92 } 93 94 /** 95 * Gets a brief hint to display about applicable subscriptions. 96 */ 97 public static function getSubscriptionHint($id) { 98 $category = self::get($id); 99 if (!$category || !isset($category['prices'])) { 100 return __(/* No subscriptions */ 'None'); 101 } 102 $prices = $category['prices']; 103 $rval = NULL; 104 foreach ($prices as $subscription => $details) { 105 if ('%none%' === $subscription) 106 continue; 107 if (NULL === $rval) 108 { 109 $rval = $subscription; 110 } 111 else 112 { 113 $rval = $subscription . ", " . $rval; 114 } 115 } 116 return $rval ?? __(/* translators: No subscriptions */ 'None'); 117 } 118 119 /** 120 * Get payment choices for GNU Taler v1 contracts 121 */ 122 public static function get_payment_choices($id, $subscriptions) { 123 $category = self::get($id); 124 if (!$category || !isset($category['prices'])) { 125 return array(); 126 } 127 128 $max_cache = time() + 3600; 129 $choices = array(); 130 $prices = $category['prices']; 131 132 foreach ($category['prices'] as $token_family_slug => $currency_map) { 133 if ($token_family_slug !== '%none%') { 134 $subscription = $subscriptions[$token_family_slug]; 135 $expi = $subscription['valid_before_s'] ?? 0; 136 if ($expi < time()) 137 continue; // already expired 138 $max_cache = min ($max_cache, 139 $expi); 140 } 141 foreach ($currency_map as $currency_code => $price) { 142 $inputs = array(); 143 144 if ($token_family_slug !== '%none%') { 145 $inputs[] = array( 146 'type' => 'token', 147 'token_family_slug' => $token_family_slug, 148 'count' => 1 149 ); 150 151 $description = sprintf( 152 /* translators: placeholder is the currency code (like "USD" or "EUR") */ 153 __('Pay in %s with subscription', 'taler-turnstile'), 154 $currency_code 155 ); 156 157 $choices[] = array( 158 'amount' => $currency_code . ':' . $price, 159 'description' => $description, 160 'inputs' => $inputs 161 ); 162 163 // Check if subscription can be purchased 164 $subscription_price = self::get_subscription_price($token_family_slug, $currency_code); 165 166 if ($subscription_price !== null) { 167 $outputs = array( 168 array( 169 'type' => 'token', 170 'token_family_slug' => $token_family_slug, 171 'count' => 1 172 ) 173 ); 174 175 $description = sprintf( 176 /* translators: placeholder is the currency code (like "USD" or "EUR") */ 177 __('Buy subscription in %s', 'taler-turnstile'), 178 $currency_code 179 ); 180 181 $total_price = floatval($subscription_price) + floatval($price); 182 183 $choices[] = array( 184 'amount' => $currency_code . ':' . $total_price, 185 'description' => $description, 186 'outputs' => $outputs 187 ); 188 } 189 } else { 190 // No subscription case 191 $description = sprintf( 192 /* translators: placeholder is the currency code (like "USD" or "EUR") */ 193 __('Pay in %s', 'taler-turnstile'), 194 $currency_code 195 ); 196 197 $choices[] = array( 198 'amount' => $currency_code . ':' . floatval($price), 199 'description' => $description, 200 'inputs' => $inputs 201 ); 202 } 203 } 204 } 205 return $choices; 206 } 207 208 /** 209 * Get subscription price for a token family and currency 210 */ 211 private static function get_subscription_price($token_family_slug, $currency_code) { 212 $subscription_prices = get_option('taler_turnstile_subscription_prices', array()); 213 214 if (isset($subscription_prices[$token_family_slug][$currency_code])) { 215 return $subscription_prices[$token_family_slug][$currency_code]; 216 } 217 218 return null; 219 } 220 }