turnstile

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

PriceCategoryForm.php (5629B)


      1 <?php
      2 
      3 /**
      4  * @file
      5  * Location: src/Form/PriceCategoryForm.php
      6  *
      7  * Form handler for price category add and edit forms.
      8  */
      9 
     10 namespace Drupal\taler_turnstile\Form;
     11 
     12 use Drupal\Core\Entity\EntityForm;
     13 use Drupal\Core\Form\FormStateInterface;
     14 use Drupal\taler_turnstile\TalerMerchantApiService;
     15 use Symfony\Component\DependencyInjection\ContainerInterface;
     16 
     17 /**
     18  * Form handler for the price category add and edit forms.
     19  */
     20 class PriceCategoryForm extends EntityForm {
     21 
     22   /**
     23    * The Turnstile API service.
     24    *
     25    * @var \Drupal\taler_turnstile\TalerMerchantApiService
     26    */
     27   protected $apiService;
     28 
     29   /**
     30    * Constructs a PriceCategoryForm object.
     31    *
     32    * @param \Drupal\taler_turnstile\TalerMerchantApiService $api_service
     33    *   The API service.
     34    */
     35   public function __construct(TalerMerchantApiService $api_service) {
     36     $this->apiService = $api_service;
     37   }
     38 
     39   /**
     40    * {@inheritdoc}
     41    */
     42   public static function create(ContainerInterface $container) {
     43     return new static(
     44       $container->get('taler_turnstile.api_service')
     45     );
     46   }
     47 
     48   /**
     49    * {@inheritdoc}
     50    */
     51   public function form(array $form, FormStateInterface $form_state) {
     52     $form = parent::form($form, $form_state);
     53     /** @var TurnstilePriceCategory $price_category */
     54     $price_category = $this->entity;
     55 
     56     $form['label'] = [
     57       '#type' => 'textfield',
     58       '#title' => $this->t('Name'),
     59       '#maxlength' => 255,
     60       '#default_value' => $price_category->label(),
     61       '#description' => $this->t('The name of the price category.'),
     62       '#required' => TRUE,
     63     ];
     64 
     65     $form['id'] = [
     66       '#type' => 'machine_name',
     67       '#default_value' => $price_category->id(),
     68       '#machine_name' => [
     69         'exists' => '\Drupal\taler_turnstile\Entity\TurnstilePriceCategory::load',
     70       ],
     71       '#disabled' => !$price_category->isNew(),
     72     ];
     73 
     74     $form['description'] = [
     75       '#type' => 'textarea',
     76       '#title' => $this->t('Description'),
     77       '#default_value' => $price_category->getDescription(),
     78       '#description' => $this->t('A description of this price category.'),
     79     ];
     80 
     81     // Get subscriptions and currencies from API.
     82     $subscriptions = $this->apiService->getSubscriptions();
     83     $currencies = $this->apiService->getCurrencies();
     84 
     85     if (empty($subscriptions) || empty($currencies)) {
     86       $this->messenger()->addWarning($this->t('Unable to load subscriptions or currencies from API. Please check your configuration.'));
     87     }
     88 
     89     $form['prices'] = [
     90       '#type' => 'fieldset',
     91       '#title' => $this->t('Prices'),
     92       '#tree' => TRUE,
     93     ];
     94 
     95     $existing_prices = $price_category->getPrices();
     96 
     97     foreach ($subscriptions as $subscription_id => $subscription) {
     98       $subscription_label = $subscription['label'] ?? $subscription['name'];
     99 
    100       $form['prices'][$subscription_id] = [
    101         '#type' => 'details',
    102         '#title' => $subscription_label,
    103         '#open' => ($subscription_id === '%none%'),
    104       ];
    105 
    106       foreach ($currencies as $currency) {
    107         $currency_code = $currency['code'] ?? $currency['name'];
    108         $currency_label = $currency['label'] ?? $currency['code'];
    109 
    110         $form['prices'][$subscription_id][$currency_code] = [
    111           '#type' => 'number',
    112           '#title' => $currency_label,
    113           '#default_value' => $existing_prices[$subscription_id][$currency_code] ?? '',
    114           '#min' => 0,
    115           '#step' => $currency['step'] ?? 0.01,
    116           '#size' => 20,
    117           '#description' => $this->t('Leave empty for no price.'),
    118         ];
    119       }
    120     }
    121 
    122     return $form;
    123   }
    124 
    125 
    126   /**
    127    * {@inheritdoc}
    128    */
    129   public function validateForm(array &$form, FormStateInterface $form_state) {
    130     parent::validateForm($form, $form_state);
    131 
    132     $prices = $form_state->getValue('prices');
    133     $ok = FALSE;
    134     if (is_array($prices)) {
    135       foreach ($prices as $subscription_id => $currencies) {
    136         if (is_array($currencies)) {
    137           foreach ($currencies as $currency_code => $price) {
    138             // Skip empty values as they are allowed.
    139             if ($price === '' || $price === NULL) {
    140               continue;
    141             }
    142 
    143             // Validate that the price is a valid non-negative number.
    144             if (!is_numeric($price) || $price < 0) {
    145               $form_state->setErrorByName(
    146                 "prices][${subscription_id}][${currency_code}",
    147                 $this->t('Prices cannot be negative.')
    148               );
    149             }
    150             $ok = TRUE;
    151           }
    152         }
    153       }
    154     }
    155     if (! $ok) {
    156       $form_state->setErrorByName(
    157         "",
    158         $this->t('At least one price must be set.')
    159       );
    160     }
    161   }
    162 
    163 
    164   /**
    165    * {@inheritdoc}
    166    */
    167   public function save(array $form, FormStateInterface $form_state) {
    168     $price_category = $this->entity;
    169 
    170     // Filter out empty prices.
    171     $prices = $form_state->getValue('prices');
    172     $filtered_prices = [];
    173     foreach ($prices as $subscription_id => $currencies) {
    174       foreach ($currencies as $currency_code => $price) {
    175         if ($price !== '') {
    176           $filtered_prices[$subscription_id][$currency_code] = $price;
    177         }
    178       }
    179     }
    180 
    181     $price_category->setPrices($filtered_prices);
    182     $status = $price_category->save();
    183 
    184     if ($status === SAVED_NEW) {
    185       $this->messenger()->addStatus($this->t('Created the %label price category.', [
    186         '%label' => $price_category->label(),
    187       ]));
    188     }
    189     else {
    190       $this->messenger()->addStatus($this->t('Updated the %label price category.', [
    191         '%label' => $price_category->label(),
    192       ]));
    193     }
    194 
    195     $form_state->setRedirectUrl($price_category->toUrl('collection'));
    196   }
    197 
    198 }