SubscriptionPricesForm.php (6000B)
1 <?php 2 3 namespace Drupal\taler_turnstile\Form; 4 5 use Drupal\Core\Form\ConfigFormBase; 6 use Drupal\Core\Form\FormStateInterface; 7 use Drupal\Core\Config\ConfigFactoryInterface; 8 use Drupal\Core\Url; 9 use Drupal\taler_turnstile\TalerMerchantApiService; 10 use Symfony\Component\DependencyInjection\ContainerInterface; 11 12 /** 13 * Configure subscription prices. 14 */ 15 class SubscriptionPricesForm extends ConfigFormBase { 16 17 /** 18 * The Taler Merchant API service. 19 * 20 * @var \Drupal\taler_turnstile\TalerMerchantApiService 21 */ 22 protected $apiService; 23 24 /** 25 * Constructs a SubscriptionPricesForm object. 26 * 27 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory 28 * The factory for configuration objects. 29 * @param \Drupal\taler_turnstile\TalerMerchantApiService $api_service 30 * The API service. 31 */ 32 public function __construct(ConfigFactoryInterface $config_factory, TalerMerchantApiService $api_service) { 33 parent::__construct($config_factory); 34 $this->apiService = $api_service; 35 } 36 37 /** 38 * {@inheritdoc} 39 */ 40 public static function create(ContainerInterface $container) { 41 return new static( 42 $container->get('config.factory'), 43 $container->get('taler_turnstile.api_service') 44 ); 45 } 46 47 /** 48 * {@inheritdoc} 49 */ 50 protected function getEditableConfigNames() { 51 return ['taler_turnstile.settings']; 52 } 53 54 /** 55 * {@inheritdoc} 56 */ 57 public function getFormId() { 58 return 'taler_turnstile_subscription_prices_form'; 59 } 60 61 /** 62 * {@inheritdoc} 63 */ 64 public function buildForm(array $form, FormStateInterface $form_state) { 65 $config = $this->config('taler_turnstile.settings'); 66 67 // Check if backend is configured 68 $backend_url = $config->get('payment_backend_url'); 69 $access_token = $config->get('access_token'); 70 71 if (empty($backend_url) || empty($access_token)) { 72 $this->messenger()->addError( 73 $this->t('Turnstile payment backend is not configured. Please <a href="@url">configure the backend</a> first.', [ 74 '@url' => Url::fromRoute('taler_turnstile.settings')->toString(), 75 ]) 76 ); 77 return parent::buildForm($form, $form_state); 78 } 79 80 $form['description'] = [ 81 '#type' => 'item', 82 '#markup' => $this->t('<p>Set the price for buying each subscription type in different currencies. Leave a field empty to prevent users from buying that subscription with that currency.</p>'), 83 ]; 84 85 // Get subscriptions and currencies from API. 86 $subscriptions = $this->apiService->getSubscriptions(); 87 $currencies = $this->apiService->getCurrencies(); 88 89 if (empty($currencies)) { 90 $this->messenger()->addError($this->t('Unable to load currencies from the API. Please check your backend configuration.')); 91 return parent::buildForm($form, $form_state); 92 } 93 94 if (empty($subscriptions)) { 95 $this->messenger()->addWarning($this->t('No subscriptions configured in Taler merchant backend.')); 96 return parent::buildForm($form, $form_state); 97 } 98 99 $form['subscription_prices'] = [ 100 '#type' => 'fieldset', 101 '#title' => $this->t('Subscription Prices'), 102 '#description' => $this->t('Set the price for buying each subscription type in different currencies.'), 103 '#tree' => TRUE, 104 ]; 105 106 $existing_prices = $config->get('subscription_prices') ?: []; 107 108 foreach ($subscriptions as $subscription_id => $subscription) { 109 $subscription_label = $subscription['label'] ?? $subscription['name']; 110 111 // Skip the %none% case as you can't buy "no subscription" 112 if ($subscription_id === '%none%') { 113 continue; 114 } 115 116 $form['subscription_prices'][$subscription_id] = [ 117 '#type' => 'details', 118 '#title' => $subscription_label, 119 '#description' => $subscription['description'] ?? '', 120 '#open' => TRUE, 121 ]; 122 123 foreach ($currencies as $currency) { 124 $currency_code = $currency['code']; 125 $currency_label = $currency['label'] ?? $currency['code']; 126 127 $form['subscription_prices'][$subscription_id][$currency_code] = [ 128 '#type' => 'number', 129 '#title' => $currency_label, 130 '#default_value' => $existing_prices[$subscription_id][$currency_code] ?? '', 131 '#min' => 0, 132 '#step' => $currency['step'] ?? 0.01, 133 '#size' => 20, 134 '#description' => $this->t('Leave empty to prevent buying this subscription with @currency.', [ 135 '@currency' => $currency_code, 136 ]), 137 ]; 138 } // for all currencies 139 } // for all subscriptions 140 141 return parent::buildForm($form, $form_state); 142 } 143 144 /** 145 * {@inheritdoc} 146 */ 147 public function validateForm(array &$form, FormStateInterface $form_state) { 148 parent::validateForm($form, $form_state); 149 150 // Validate subscription prices 151 $subscription_prices = $form_state->getValue('subscription_prices'); 152 if (is_array($subscription_prices)) { 153 foreach ($subscription_prices as $subscription_id => $currencies) { 154 if (is_array($currencies)) { 155 foreach ($currencies as $currency_code => $price) { 156 // Skip empty values as they are allowed 157 if ($price === '' || $price === NULL) { 158 continue; 159 } 160 161 // Validate that the price is a valid non-negative number 162 if (!is_numeric($price) || $price < 0) { 163 $form_state->setErrorByName( 164 "subscription_prices][{$subscription_id}][{$currency_code}", 165 $this->t('Subscription prices cannot be negative.') 166 ); 167 } 168 } 169 } 170 } 171 } 172 } 173 174 175 /** 176 * {@inheritdoc} 177 */ 178 public function submitForm(array &$form, FormStateInterface $form_state) { 179 $config = $this->config('taler_turnstile.settings'); 180 $subscription_prices = $form_state->getValue('subscription_prices'); 181 182 $config->set('subscription_prices', $subscription_prices); 183 $config->save(); 184 185 parent::submitForm($form, $form_state); 186 } 187 188 }