turnstile

Drupal paywall plugin
Log | Files | Refs | README | LICENSE

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 }